将一个类型为Object的ArrayList转换为另一个类型为Object的ArrayList。

huangapple go评论47阅读模式
英文:

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 &quot;status&quot;. <sup>Demo</sup>

final Map&lt;Boolean, List&lt;Filter&gt;&gt; parts = list.stream()
        .collect(Collectors.partitioningBy(f -&gt; &quot;status&quot;.equals(f.getKey())));
final Object[] statuses = parts.get(true).stream().map(Filter::getValue).toArray();
final List&lt;Filter&gt; result = parts.get(false);
if (statuses.length != 0) {
    result.add(0, new Filter(&quot;status&quot;, &quot;in&quot;, statuses));
}

For multiple keys, you can use Collectors.groupingBy. <sup>Demo</sup>

final Map&lt;String, List&lt;Filter&gt;&gt; map = list.stream().collect(Collectors.groupingBy(Filter::getKey, LinkedHashMap::new, Collectors.toList()));
final List&lt;Filter&gt; result = map.entrySet().stream()
        .map(e -&gt; e.getValue().size() &gt; 1
                ? new Filter(e.getKey(), &quot;in&quot;, 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 values;
// getter setter constructor
}

现在首先使用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 resList = new ArrayList<>(resMap.values()); // 从映射值创建列表

英文:

First, create a class for your response with List of value

class FilterRes{
  private String key;
  private String operator;
  private List&lt;Object&gt; 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&lt;Integer, FilterRes&gt; resMap = list.stream()
                .map(s -&gt; new FilterRes(s.getKey(), s.getOperator(),
                                        new ArrayList&lt;&gt;(Arrays.asList(s.getValue()))))
                .collect(Collectors.toMap(FilterRes::getKey, e -&gt; e,    
                                    (a, b) -&gt; new FilterRes(a.getKey(), &quot;in&quot;, 
                                                Stream.concat(a.getValue().stream(),
                                                              b.getValue().stream())
                                                         .collect(Collectors.toList()))));

List&lt;FilterRes&gt; resList= new ArrayList(resMap.values()); // Create list from map values

huangapple
  • 本文由 发表于 2020年7月30日 02:31:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63160228.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定

  • 开发者交流平台

    本页二维码