英文:
Java transform ArrayList of type object to another ArrayList of type object
问题
以下是翻译好的部分:
我有一个带有成员变量的类:
class Filter {
private String key;
private String operator;
private Object value;
}
以及以下类型为Filter的List:
[
{
key: status,
operator: equal,
value: active
},
{
key: status,
operator: equal,
value: inactive
},
{
key: name,
operator: equal,
value: jhon
},
{
key: id,
operator: equal,
value: 123
}
]
我想将上述的`List`转换成一个新的`List`,如下所示,如果键相同 `key: status`,则在新列表中只需要一个条目,值为列表类型 `value: [active, inactive]`,并且操作符将为 `IN`:
[
{
key: status,
operator: in,
value: [active, inactive]
},
{
key: name,
operator: equal,
value: jhon
},
{
key: id,
operator: equal,
value: 123
}
]
如何以最佳和高效的方式实现此解决方案,最好使用Java 8的流和Lambda表达式?希望避免传统的for循环。
请注意,我已经删除了不需要的内容并只保留了翻译部分。
英文:
I have a class with member variables:
class Filter{
private String key;
private String operator;
private Object value;
}
And List of Type Filter as below:
[
{
key: status,
operator:equal,
value: active
},
{
key: status,
operator:equal,
value: inactive
},
{
key: name,
operator:equal,
value: jhon
},
{
key: id,
operator:equal,
value: 123
}
]
I want to transform the above List
into a new List
as below where if the key is same key: status
then in new list need to have only one entry with value is in list type value: [active, inactive]
and operator will be IN
[
{
key: status,
operator:in,
value: [active, inactive]
},
{
key: name,
operator:equal,
value: jhon
},
{
key: id,
operator:equal,
value: 123
}
]
What is the best and efficient way to achieve this solution, preferably using Java 8 stream and lambdas?
Wanted to avoid traditional for loop.
答案1
得分: 3
你可以使用 Collectors.partitioningBy
根据过滤器的键是否为 "status"
将 List
分成两部分。 <sup>演示</sup>
final Map<Boolean, List<Filter>> parts = list.stream()
.collect(Collectors.partitioningBy(f -> "status".equals(f.getKey())));
final Object[] statuses = parts.get(true).stream().map(Filter::getValue).toArray();
final List<Filter> result = parts.get(false);
if (statuses.length != 0) {
result.add(0, new Filter("status", "in", statuses));
}
对于多个键,你可以使用 Collectors.groupingBy
。 <sup>演示</sup>
final Map<String, List<Filter>> map = list.stream().collect(Collectors.groupingBy(Filter::getKey, LinkedHashMap::new, Collectors.toList()));
final List<Filter> result = map.entrySet().stream()
.map(e -> e.getValue().size() > 1
? new Filter(e.getKey(), "in", e.getValue().stream().map(Filter::getValue).toArray())
: e.getValue().get(0))
.collect(Collectors.toList());
英文:
You can use Collectors.partitioningBy
to split the List
into two parts based on whether or not the Filter's key is "status"
. <sup>Demo</sup>
final Map<Boolean, List<Filter>> parts = list.stream()
.collect(Collectors.partitioningBy(f -> "status".equals(f.getKey())));
final Object[] statuses = parts.get(true).stream().map(Filter::getValue).toArray();
final List<Filter> result = parts.get(false);
if (statuses.length != 0) {
result.add(0, new Filter("status", "in", statuses));
}
For multiple keys, you can use Collectors.groupingBy
. <sup>Demo</sup>
final Map<String, List<Filter>> map = list.stream().collect(Collectors.groupingBy(Filter::getKey, LinkedHashMap::new, Collectors.toList()));
final List<Filter> result = map.entrySet().stream()
.map(e -> e.getValue().size() > 1
? new Filter(e.getKey(), "in", e.getValue().stream().map(Filter::getValue).toArray())
: e.getValue().get(0))
.collect(Collectors.toList());
答案2
得分: 2
class FilterRes {
private String key;
private String operator;
private List
现在首先使用map()
将Filter
转换为FilterRes
,然后使用Collectors.toMap
收集为映射,并在合并函数中合并组。接下来,从ArrayList中获取值。
Map<Integer, FilterRes> resMap = list.stream()
.map(s -> new FilterRes(s.getKey(), s.getOperator(),
new ArrayList<>(Arrays.asList(s.getValue()))))
.collect(Collectors.toMap(FilterRes::getKey, e -> e,
(a, b) -> new FilterRes(a.getKey(), "in",
Stream.concat(a.getValue().stream(),
b.getValue().stream())
.collect(Collectors.toList()))));
List
英文:
First, create a class for your response with List of value
class FilterRes{
private String key;
private String operator;
private List<Object> values;
// getter setter constractor
}
Now first transform Filter
into FilterRes
using map()
then collect as map using Collectors.toMap
and merge group in merge function. Then get the values in an ArrayList
Map<Integer, FilterRes> resMap = list.stream()
.map(s -> new FilterRes(s.getKey(), s.getOperator(),
new ArrayList<>(Arrays.asList(s.getValue()))))
.collect(Collectors.toMap(FilterRes::getKey, e -> e,
(a, b) -> new FilterRes(a.getKey(), "in",
Stream.concat(a.getValue().stream(),
b.getValue().stream())
.collect(Collectors.toList()))));
List<FilterRes> resList= new ArrayList(resMap.values()); // Create list from map values
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论