Home > Enterprise >  Get duplicates object in a List java
Get duplicates object in a List java

Time:02-26

I have a list of product exampe

List<Product> productList = [product1, product2,product2, product3, product3, product5];

My product class is

public class Product {
 private long productId;
 private String productName;
 private double productPrice;
 ... getters and setters
}

I want to have two list : the first returns only product which occur more than once and the second returns product which occur only once

I am using Streams with java 8

List<Product> productMoreThanOnce = new ArrayList<>();
List<Product> productOnlyOnce = new ArrayList<>();
productMoreThanOnce = productList.stream().filter(e-> Collections.frequency(productList, e) > 1).distinct().collect(Collectors.toList());

productOnlyOnce  = productList.stream().filter(e-> Collections.frequency(productList, e) == 1).distinct().collect(Collectors.toList());

but productMoreThanOnce doesn't returns duplicated product => [product2,product3]

what is the best way to do this ?

CodePudding user response:

You can group within the stream:

Map<Product, Long> map = productList.stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

here each key has associated number of occurrences as value.

Then you can retrieve unique elements:

List<Product> unique = map.entrySet().stream()
    .filter(e -> e.getValue() == 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

And retrieve duplicate elements:

List<Product> duplicate = map.entrySet().stream()
    .filter(e -> e.getValue() > 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

CodePudding user response:

Add and override equals and hashcode methods in your Product class, if you have not already done so. Example:

@Override
public boolean equals(final Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof Product)) {
        return false;
    }
    final Product product = (Product) o;
    return productId == product.productId && Double.compare(product.productPrice, productPrice) == 0
            && Objects.equals(productName, product.productName);
}

@Override
public int hashCode() {
    return Objects.hash(productId, productName, productPrice);
}

You can then use a partitioning collector from the streams api:

Map<Boolean,List<Product>> map = productList.stream()
        .collect(Collectors.partitioningBy(e -> Collections.frequency(productList, e) > 1));

List<Product> productMoreThanOnce = map.get(true);
List<Product> productOnlyOnce     = map.get(false);
  • Related