I need to implement a HashSet<Region> . If you simply add 2 identical objects of the Region class to the hashset (with the same value of the value ), then the hashset will contain both objects, and not one. How to avoid it? How to make it so that no objects are added that are identical in the value field. And how in such a set to establish the presence or absence of another instance of the class? ( сontain does not roll).
Here is the Region class

 public class Region { private Regions value; public Regions getValue() { return value; } public void setValue(Regions value) { this.value = value; } @Override public boolean equals(Object obj) { Region otherRegion = (Region) obj; return this.value.equals(otherRegion.getValue()); } static enum Regions { region1("region - 1"), region2("region - 2"), region3("region - 3"), region4("region - 4"); private String value; Regions(String value) { this.value = value; } public String toString() { return value; } } 



  HashSet<Region> q = new HashSet<Region>(); Region qwe1 = new Region(); qwe1.setValue(Region.Regions.region1); Region qwe2 = new Region(); qwe2.setValue(Region.Regions.region1); q.add(qwe1); q.add(qwe2); Region qwe3 = new Region(); qwe3.setValue(Region.Regions.region2); out.println(qwe1.equals(qwe2)); out.println(q.size()); out.println(q.contains(qwe3)); 

And here is your own result:

 true 2 false 

    1 answer 1

    For HashSet <Region> to work correctly, you need to override the equals method in the Region class. Those. show that from your point of view is the equivalence of regions.

    Also, for faster access to objects in the Set (by avoiding collisions), override the hashCode method. But this is the case if you have your own unique identifier (id from the database, for example). You are not required now.

    equals, hashCode are called inside a HashSet when trying to add an object.

    More on your code: why in the Region enum class of these regions? Just make a box

     private String name; 

    as the name of the region.

    And in the equals method compare on it:

     @Override boolean equals(Object otherObj) { // Каст к Region Region otherRegion = (Region) otherObj; // Обязательно проверки на null // instanceof, равенство ссылок на объект return this.name.equals(otherRegion.getName()); } 

    And then add the regions to Set:

     HashSet<Region> regions = new HashSet<Region>(); Region reg1 = new Region(); reg1.setName("East"); Region reg2 = new Region(); reg2.setName("West"); Region reg3 = new Region(); reg3.setName("East"); regions.add(reg1); regions.add(reg2); regions.add(reg3); // Не добавится 
    • Enum regions are needed so that they take a certain value, and not just an abstract String. How does the Object type know the getName () method? - Stas0n
    • Right. Forgot caste to the Region. Corrected. - pkamozin
    • And something all the same does not work ... As before, I can add 2 identical Regions to the set and, moreover, contains, gives fallse, when it should produce true - added code. - Stas0n
    • The equals method was enough for the case when I suggested typing a String name. But now, when you left enum Regions, it’s time for hashCode :-) Add to Region: @Override public int hashCode () {return this.value.toString (). HashCode (); } Without this method, the hash code for the element was generated differently each time (the native Object method). Now for each element enum returns the same. - pkamozin
    • Yeah, it works, thanks !!!! Do you think it is worth leaving enum in the classroom or is it better to take it out? - Stas0n