Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't java.util.HashSet have a get(Object o) method?

Tags:

java

hashset

I've seen other questions about getting objects from Set's based on index value and I understand why that is not possible. But I haven't been able to find a good explanation for why a get by object is not allowed so thought I would ask.

HashSet is backed by a HashMap so getting an object from it should be pretty straightforward. As it is now, it appears I would have to iterate over each item in the HashSet and test for equality which seems unnecessary.

I could just use a Map but I have no need for a key:value pair, I just need a Set.

For example say I have Foo.java:

package example;

import java.io.Serializable;

public class Foo implements Serializable {

    String _id;
    String _description;

    public Foo(String id){
        this._id = id
    }

    public void setDescription(String description){
        this._description = description;
    }

    public String getDescription(){
        return this._description;
    }

    public boolean equals(Object obj) {
        //equals code, checks if id's are equal
    }

    public int hashCode() {
        //hash code calculation
    }

}

and Example.java:

package example;

import java.util.HashSet;

public class Example {

    public static void main(String[] args){
        HashSet<Foo> set = new HashSet<Foo>();

        Foo foo1 = new Foo("1");
        foo1.setDescription("Number 1");

        set.add(foo1);
        set.add(new Foo("2"));

        //I want to get the object stored in the Set, so I construct a object that is 'equal' to the one I want.
        Foo theFoo = set.get(new Foo("1")); //Is there a reason this is not allowed?
        System.out.println(theFoo.getDescription); //Should print Number 1
    }

}

Is it because the equals method is meant to test for "absolute" equality rather than "logical" equality (in which case contains(Object o) would be sufficient)?

like image 219
FGreg Avatar asked Dec 13 '12 15:12

FGreg


People also ask

Is there a GET method in HashSet?

HashSet does not have a get method to retrieve elements. HashSet implements the Set interface. The Set is a collection with no duplicates.

Does Set have get method in Java?

As java set doesn't provide get method, I need to iterate over the set in my code and update the name when I find the equal object (i.e. when ID matches). If you had get method, this code could have been shortened.

Does HashSet contain O 1?

On average, the contains() of HashSet runs in O(1) time. Getting the object's bucket location is a constant time operation. Taking into account possible collisions, the lookup time may rise to log(n) because the internal bucket structure is a TreeMap.


4 Answers

Java Map/Collection Cheat Sheet

Will it contain key/value pair or values only?

1) If it contains pairs, the choice is a map. Is order important?

. 1-1) If yes, follow insertion order or sort by keys?

. . 1-1-1) If ordered, LinkedHashMap

. . 1-1-2) If sorted, TreeMap

. 1-2) If order is not important, HashMap

2) If it stores only values, the choice is a collection. Will it contain duplicates?

. 2-1) If yes, ArrayList

. 2-2) If it will not contain duplicates, is primary task searching for elements (contains/remove)?

. . 2-2-1) If no, ArrayList

. . 2-2-2) If yes, is order important?

. . . 2-2-2-1) If order is not important, HashSet

. . . 2-2-2-2) If yes, follow insertion order or sort by values?

. . . . 2-2-2-2-1) if ordered, LinkedHashSet

. . . . 2-2-2-2-2) if sorted, TreeSet

like image 118
Rasshu Avatar answered Oct 09 '22 17:10

Rasshu


A Set is a Collection of objects which treats a.equals(b) == true as duplicates, so it doesn't make sense to try to get the same object you already have.

If you are trying to get(Object) from a collection, a Map is likely to be more appropriate.

What you should write is

Map<String, String> map = new LinkedHashMap<>();

map.put("1", "Number 1");
map.put("2", null);
String description = map.get("1");

if an object is not in the set (based on equals), add it, if it is in the set (based on equals) give me the set's instance of that object

In the unlikely event you need this you can use a Map.

Map<Bar, Bar> map = // LinkedHashMap or ConcurrentHashMap

Bar bar1 = new Bar(1);
map.put(bar1, bar1);

Bar bar1a = map.get(new Bar(1));
like image 21
Peter Lawrey Avatar answered Oct 09 '22 17:10

Peter Lawrey


If you want to know that new Foo("1"); object is already present in the set then you need to use contains method as:

boolean present =  set.contains(new Foo("1"));

The get kind of method i.e. set.get(new Foo("1")); is not supported because it doesn't make sense. You are already having the object i.e. new Foo("1") then what extra information you would be looking through get method.

like image 5
Yogendra Singh Avatar answered Oct 09 '22 16:10

Yogendra Singh


Your last sentence is the answer.

get(Object o) would run through the HashSet looking for another object being equal to o (using equals(o) method). So it is indeed the same as contains(o), only not returning the same result.

like image 5
xlecoustillier Avatar answered Oct 09 '22 15:10

xlecoustillier