英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论