【问题标题】:How do I get list of only duplicate objects from a list如何从列表中获取仅重复对象的列表
【发布时间】:2019-07-16 16:32:26
【问题描述】:

如何从列表中获取仅重复对象的列表。

我有一个对象的 ArrayList

Pojo Class
Class Abc {
int id ;
String name;
Date startDate;
int rowNum;
......
}

Example Data:
id    name      startDate    rowNum
110   Art       01-Jan-2018   1
120   Art       01-Jan-2019   1
121   Science   01-Jan-2018   2
122   Computer  01-Jan-2018   3
..
190   Math      01-May-2020   40
180   Math      04-Aug-2040   40
456   Math      01-Dec-2060   40

Abc 列表有时包含 - 4000 条或更多记录。 我想在单独的列表中获取重复 rowNum 的 id、name、startDate。

Ex: List2 should contains (duplicate records only)
id    name      startDate    rowNum
110   Art       01-Jan-2018   1
120   Art       01-Jan-2019   1
.....
190   Math      01-May-2020   40
180   Math      04-Aug-2040   40
456   Math      01-Dec-2060   40

如何从列表中获取仅重复对象的列表。

【问题讨论】:

  • id 不同,它们不是重复的。
  • 我不认为通过查看标题从 Java 8 中的列表中提取重复对象是重复的。另一个问题更具体到它自己的类和数据
  • 正如我提到的,重复应该基于 rowNum 而不是 Id..

标签: java collections java-stream


【解决方案1】:
  1. 按行数对元素进行分组(在Map<Integer,List<Abc>> 中)
  2. 对于每一行num,保留列表大小为>= 2的列表元素
  3. 收集过滤/保留的元素

它会给出如下代码:

List<Abc> abcList = ...;

Map<Integer,List<Abc>> elementsByRowNum =
abcList.stream()
       .collect(groupingBy(Abc::getRowNum));

List<Abc> abcWithDupList = 
elementsByRowNum.values().stream()
               .filter(v-> v.size()>=2)
               .flatMap(List::stream)
               .collect(toList());

你也可以用更紧凑的方式(没有地图):

List<Abc> abcWithDupList = 
abcList.stream()
       .collect(groupingBy(Abc::getRowNum))
       .values()
       .stream()  // Stream<List<Abc>>
       .filter(l-> l.size()>=2)
       .flatMap(List::stream)
       .collect(toList());

【讨论】:

  • 我正在寻找 java 8 流
  • 我的解释也适用于 Java 8。我更新了一个示例代码。
  • flatmapping时不应该是flatMap(List::stream)而不是.flatMap(v.stream())吗?
  • @Eritrean 确实如此。我忘记了 .flatMap(v-&gt;v.stream()) 的 lambda 参数
【解决方案2】:

相等不是万能运算,存在很多方法来检查两个元素是否相等。这就是显式注入equality 定义的原因。

另一方面,您的问题是检索所有重复元素或仅其中一个。

如果你只想要其中一个,Set 操作是解决它的通用解决方案。

使用 Java,不存在设置自定义比较器的标准方法,但您可以使用流:

xs.stream()
    .collect(groupingBy(youCustomKey, minBy((a, b) -> 0)))
    .values().stream().map(Optional::get).collect(toList())

在这里,对于每个重复组(包括单例元素!),您只会得到一个。

如果您希望yourCustomKey 下的所有重复元素都可以这样做

xs.stream()
    .collect(groupingBy(yourCustomKey, toList()))
    .values().stream()
    .filter(x -> x.size() > 1)
    .flatMap(Collection::stream)
    .collect(toList())

在这里,你得到所有重复的元素。

在这两种情况下,您都可以设置自定义yourCustomKey,因为您说“复制应该基于 rowNum” 然后

Function<Abc, Integer> yourCustomKey = Abc::getRowNum;

(显然你可以避免这个定义)。

以字符串为例:

List<String> xs = asList("aaa", "bb", "rrr", "ff", "qqqq");

List<String> ys1 = xs.stream()
        .collect(groupingBy(String::length, minBy((a, b) -> 0)))
        .values().stream().map(Optional::get).collect(toList());

List<String> ys2 = xs.stream()
        .collect(groupingBy(String::length, toList()))
        .values().stream()
        .filter(x -> x.size() > 1)
        .flatMap(Collection::stream)
        .collect(toList());

System.out.printf("ys1: %s%n", String.join(", ", ys1));
System.out.printf("ys2: %s%n", String.join(", ", ys2));

返回:

ys1: bb, aaa, qqqq
ys2: bb, ff, aaa, rrr

【讨论】:

    猜你喜欢
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    • 2021-10-25
    • 1970-01-01
    • 2020-01-07
    • 2011-06-26
    • 1970-01-01
    相关资源
    最近更新 更多