5

I am trying Converting a list of objects to a set of objects to make sure if there is no duplicates exists in the collection. I am trying it using Streams.

I have a class Product as below :

class Product{  
int id;  
String name;  
float price;  
public Product(int id, String name, float price) {  
    this.id = id;  
    this.name = name;  
    this.price = price;  
}  
 public String getName()
 {
     return this.name;
 }
 public int getId()
 {
     return this.id;

 }
 public float getPrice()
 {
     return this.price;
 }
 public void setName(String name)
 {
     this.name = name;
 }
 public void setId(int id)
 {
     this.id = id;
 }
 public void getPrice(float price)
 {
     this.price = price;
 }
}  

I am trying something Like:

   List<Product> productsList = new ArrayList<Product>();  

    //Adding Products  
    productsList.add(new Product(1,"HP Laptop",25000f));  
    productsList.add(new Product(2,"Dell Laptop",30000f));  
    productsList.add(new Product(3,"Lenevo Laptop",28000f));  
    productsList.add(new Product(4,"Sony Laptop",28000f));  
    productsList.add(new Product(5,"Apple Laptop",90000f));  
    productsList.add(new Product(5,"Apple Laptop",90000f)); 

I want the resultant to be stored as Set:

 Set<Product> productPriceList=productsList.stream()
 .map(p->new Product(p.getId,p.getName,p.getPrice))
 .collect(Collectors.toSet()); 

But it's not working for me. Any suggestions would be highly appriciated !

Lino
  • 19,604
  • 6
  • 47
  • 65
NawazSE
  • 593
  • 4
  • 9
  • 21

3 Answers3

9

Your code will almost compile, you just missed the parentheses off p.getId etc.:

Set<Product> productPriceList = productsList.stream()
    .map(p -> new Product(p.getId(), p.getName(), p.getPrice()))
    .collect(Collectors.toSet());

However, your Product must override equals and hashCode if you want the set to work properly. You can see this question for why.

Michael
  • 41,989
  • 11
  • 82
  • 128
4

It's not clear why you are creating new Product instances to store in the Set. You can simply create a Stream and immediately collect to a Set:

 Set<Product> productPriceList = productsList.stream().collect(Collectors.toSet()); 

However, you must override equals() and hashCode() in order for the Set created by the Stream pipeline to correctly eliminate duplicates (since the current implementation of toSet() returns a HashSet, which requires these methods to be overridden).

Of course, the same result can be obtained without Streams:

Set<Product> productPriceList = new HashSet<>(productPriceList);
Eran
  • 387,369
  • 54
  • 702
  • 768
  • I can see this working but the resultant set is still having the duplicate element. for example : the above list is still having total 6 objects where it should be 5 objects only (The last one is repeated actually). – NawazSE May 30 '18 at 14:09
  • 1
    @NawazSE whether or not you use Streams to produce the Set, you must override equals and hashCode as mentioned in my answer. – Eran May 30 '18 at 14:17
3

As @Khelwood pointed out you need to mention the rule of equality. How does JVM know when to consider two Products as equal?. The product is not a primitive data type and thus JVM only treats it as an object. Read about overriding equals and hashcode and its usage and implications. Just as an advice, It will be of great use to spend some time reading about it rather than jumping into solutions.

Edit: I see many similar answers already posted. Did not see it while writing my suggestions but looks like you got the idea why it is failing. good luck !!

  • "I see many similar answers already posted". Don't feel bad about that. It's okay to post answers that are similar to other people's answers, especially if you have a different or better way of explaining it. It should not be a race to post a (crap) answer as fast as possible, it's about providing high quality answers. I think your answer adds something that the other answers are missing so you're good in that respect. Welcome to Stack Overflow, by the way. – Michael May 30 '18 at 12:51
  • The resultant set is still having the duplicate element. for example : the above list is still having total 6 objects where it should contain 5 objects only (The last one is repeated actually). – NawazSE May 30 '18 at 14:10
  • @NawazSE Can you share the code where you have overdriven equals ? –  May 30 '18 at 14:49