3

How Do I collect in java 8 to a set by some field? for example: I have 2 object with different hashes (that's why they are two entities in the set) but I want to have a set with only one instance of it

tried this: but it gives me two students while I have only 1 unique.

Set<Man> students =
   people.stream().collect( Collectors.mapping( Man::isStudent, Collectors.toSet()));

name:"abc" , id:5 (hash 1XX)
name:"abc", id:5  (has 5XX)

and I want the set to contain only one instance

Thanks

Aubin
  • 14,617
  • 9
  • 61
  • 84
Bazuka
  • 417
  • 5
  • 16
  • 1
    `Map` may be used... – Aubin Jan 31 '17 at 09:32
  • can you write an example ? – Bazuka Jan 31 '17 at 09:35
  • Can you post your code, what have you tried? – Aubin Jan 31 '17 at 09:35
  • how do i do that ? – Bazuka Jan 31 '17 at 09:38
  • Set students = people.stream().collect(Collectors.mapping(Man::isStudent, Collectors.toSet())); – Bazuka Jan 31 '17 at 09:38
  • Possible duplicate of [Java 8 Distinct by property](http://stackoverflow.com/questions/23699371/java-8-distinct-by-property) – Roland Jan 31 '17 at 09:52
  • 2
    @Bazuka If two objects are equal, they must have the same hashcode. Are there other fields in the class that make them unequal, or is your hashcode implementation broken? Putting objects with inconsistent equal and hashCode implementations into a `Set` is not good! – marstran Jan 31 '17 at 09:57
  • can you post the `Man` class ? BTW Set data structure depends on object's `hashcode or compare` [take a look how HashSet or TreeSet works]. So how could you possible do this ? – seal Jan 31 '17 at 10:14

2 Answers2

1

You have to override the hashCode and equals. The possible implementation is:

@Override
public int hashCode() {
    return this.name.hashCode * 31 + id;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Student)) return false;

    Student s = (Student) o;

    if (!getName().equals(s.getName())) return false;
    if (getId() != appError.getStatus()) return false;

    return true;
}
xenteros
  • 15,586
  • 12
  • 56
  • 91
  • I would rather to avoid from changing my Student class. is there any other solution like sending a field into .toSet function ? – Bazuka Jan 31 '17 at 09:41
1

Best solution would be to overwrite hashCode and equals methods in your Man class. Because Set is a type of collection that would require those methods, when adding/removing any element.

If you are interested only in collection of unique elements (read only), you can reduce your collection to map, where key would be name proparety and then take the values.

Collection<Man> uniqueByName= myCollection.stream().collect(
  Map::getName,
  Function.identity()
).values();
Beri
  • 11,470
  • 4
  • 35
  • 57