从具有类似属性的List <object>创建List <set>

时间:2016-01-04 10:14:08

标签: java java-8 java-stream

class A {
  private String x;
  private String y;
  //getters and setters
}

假设我有一个A类型的对象列表。现在考虑。

A a = new A("x","something1");
A b = new A("x","something2");
A c = new A("y","something3");
A d = new A("y","something4");

List<A> aList = new ArrayList<>();

`alist` contains a, b,c ,d

我可以根据以下标准过滤列表并创建子列表列表:如果属性x的值相等,则将它们分组到子列表中吗?

所以输出应该是类似的。

List<A> someList = new ArrayList<>(); //someList contains a,b

List<A> someOtherList = new ArrayList<>(); //someOtherList contains c,d.

最终输出列表包含someList和someOtherList。

3 个答案:

答案 0 :(得分:4)

您可以使用Java 8 Stream API和groupingBy收集器:

Map<String, List<A>> result = aList.stream().collect(
                 Collectors.groupingBy(A::getX));

通过这种方式,您将获得Map,其中键是字段x的可能值,值是相应A元素的列表。

之后,您可以提取单个列表:

List<A> someList = result.get("x"); // contains a, b
List<A> someOtherList = result.get("y"); // contains c, d

如果您想按两个或更多属性进行分组,可以使用Arrays.asList作为分类器:

Map<List<Object>, List<A>> result = aList.stream().collect(
                 Collectors.groupingBy(a -> Arrays.asList(a.getX(), a.getY())));

在这里,您将有一个复合键,表示为List

答案 1 :(得分:4)

  

如果属性x的值相等,则将它们分组到子列表。

您自己说过,您需要按属性x的值对列表进行分组。使用Stream API,可以使用收集器Collectors.groupingBy(classifier)来完成。此收集器返回一个映射,其中条目是将给定分类器应用于Stream元素的结果,并将值收集到列表中。

Map<String, List<A>> map = aList.stream().collect(Collectors.groupingBy(A::getX));

此地图将包含2个条目。第一个是关键x指向元素ab;第二个是关键y指向元素cd

答案 2 :(得分:0)

@Tagir提到了一种方法,如果我想检查两个属性值的相等性。只需发布不同即可实现它。

Map<String, Collection<List<A>>> result = aList.parallelStream()
            .collect(Collectors.groupingBy(A::getX,
             Collectors.collectingAndThen(Collectors.groupingBy(A::getY), Map::values)));

parallelStream()以防万一。