1

How do I get list of only duplicate objects from a list.

I have an ArrayList of objects

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 list contains - 4000 records or more sometimes. I want to get id,name,startDate of duplicate rowNum in separate list.

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

How do I get list of only duplicate objects from a list.

  • Possible duplicate of [Extract duplicate objects from a List in Java 8](https://stackoverflow.com/questions/53164975/extract-duplicate-objects-from-a-list-in-java-8) – Dushyant Tankariya Jul 16 '19 at 08:01
  • 2
    id's are different, they are not duplicates. – Aniket Sahrawat Jul 16 '19 at 08:03
  • I dont think its duplicate to Extract duplicate objects from a List in Java 8 by looking at title. The other quesiton is more specific to its own class and data –  Jul 16 '19 at 08:04
  • as I mentioned Duplicate should be based on rowNum not Id.. –  Jul 16 '19 at 08:05

2 Answers2

1
  1. group element by row num (in a Map<Integer,List<Abc>>)
  2. for each row num, keep elements of the list which the list size is >= 2
  3. collect filtered/kept elements

It would give a code like :

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());

You could also write that in a more compact way (without the map) :

List<Abc> abcWithDupList = 
abcList.stream()
       .collect(groupingBy(Abc::getRowNum))
       .values()
       .stream()  // Stream<List<Abc>>
       .filter(l-> l.size()>=2)
       .flatMap(List::stream)
       .collect(toList());
davidxxx
  • 125,838
  • 23
  • 214
  • 215
1

Equality is not an universal operation, exists a lot of ways to check if two elements are equals or not. This is the reason to inject explicitly the equality definition.

On the other hand, your question is open to retrieve all duplicated elements or only one of them.

If you want only one of them, the Set operation is the universal solution to solve it.

Using Java, no standard way exists to set the custom comparator but you can do using streams:

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

here, you get only one for each repeated group (including singleton elements!).

If you wish all repeated element under yourCustomKey you can do

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

here, you get all repeated elements.

In both cases, you can set your custom yourCustomKey, since you say "Duplicate should be based on rowNum" then

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

(obviously you can avoid that definition).

As an example using strings:

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));

Return:

ys1: bb, aaa, qqqq
ys2: bb, ff, aaa, rrr
josejuan
  • 9,338
  • 24
  • 31