Is there a java structure like HashMap but that allows to repeat the key as well as the value ?
For example:
HashMap<Integer, String> hmap = new HashMap<>();
map.put(1, "Sport");
map.put(1, "Football");
map.put(2, "Football");
map.put(1, "Handball");
And as a result:
<1,"Sport">
<1,"Football">
<2,"Football">
<3,"Handball">
Any help would be most appreciated.
Thanks,
Nadhmanovic
There is not a structure like this built into the language. But you can use Guava's Multimap.
would using the
Map<Key, List<Value>>
help?
A List holding a object that has a Integer and a String can work for you and will also keep the order added.
But if you want to find all elements with the same key you will need a for, or a structure like Map<Integer, List<String>>
You can use MultiMap<Character,Boolean> because it allows duplicate key which exist in org.apache.commons.collections package.
or
You can use ArrayList and add the objects of the Class to the same key.
Hope this helps!
Related
Is there any way to use map or any other collection which allow us to store duplicate keys
with different values...
rather then using a List to store multiple values for same key?
Use Google Guava's MultiMap. This allows multiple values with single key
http://guava-libraries.googlecode.com/svn/tags/release03/javadoc/com/google/common/collect/Multimap.html
Map doesn't allow you to have duplicated keys. That even doesn't make sense.
Possible solution is having list(Collection) of values. Just go for it.If anything stopping you, let us know.
There is a Multimap concept. For example in guava. Multimap in guava
But it's not a part of Collection framework.
If you would not like signature like this Map<String, List<Item>>, you could easily wrap it with object. E.g.
class Items {
private List<Item> items;
public void add(Item i) {}
}
Of course it would not be possible to add items through map instance as map.add("key", item)
What about the next?:
Map<String, List<String>> map = new HashMap<>();
Add values
// add "key1" and "value1"
if (!map.containsKey("key1")) {
map.put("key1", new ArrayList<String>());
}
map.get("key1").add("value1");
// add "key1" and "value2"
if (!map.containsKey("key1")) {
map.put("key1", new ArrayList<String>());
}
map.get("key1").add("value2");
Get values
List<String> values = map.get("key1");
This with string, but can be for any type. And you don't need additional libraries.
you can use MultiMap from apache commons collections
http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/MultiMap.html
I see many examples about multimap but did not understand why Google Gauva is different?
Multimap<Integer, Set<String>> option4 = HashMultimap.create(); // Gauva
Map<Integer, Set<String>> opt = new HashMap<Integer, Set<String>>(); //Core Java
Is both above are behave same for holding data or different?
A MultiMap<A, B> associates a key of type A with a value of type Collection<B> (hence the name MultiMap)
A Map<A, B> associates a key of type A with a value of type B.
So, a MultiMap<Integer, Set<String>> can be viewed as a Map<Integer, Collection<Set<String>>. This should be obvious by reading the api documentation.
The difference is that with the second, Core Java implementation, you need to check whether the Set is there before you insert. Guava's Multimap takes care of that for you.
With Core Java:
Set<String> innerSet = opt.get(key);
if (innerSet == null) {
innerSet = new HashSet<String>();
opt.put(key, innerSet);
}
innerSet.add(value);
With Guava:
opt.put(key, value);
Guava takes care of initialising an otherwise absent Set to store the values, takes care of any threading issues (eg stops two threads from creating a new Set for the same key in parallel) and also provides a few useful methods that you'd otherwise need to implement by hand, such as getting all the values across all the Sets.
You misunderstood something. These are not even roughly equivalent:
Multimap<Integer, Set<String>> option4 = HashMultimap.create(); // Guava
Map<Integer, Set<String>> opt = new HashMap<Integer, Set<String>>(); //Core Java
In your example, opt4 would map a single Integer to a Collection of Sets of Strings.
That's exactly the point of using a Multimap, you don't have to explicitly deal with the second dimension. So in fact, the correct (equivalent) declaration would be:
SetMultimap<Integer, String> multimap = HashMultimap.create(); // Guava
and you can get a map view like this:
Map<Integer, Set<String>> mapView = multimap.asMap();
Nope, MultiMap means that there would be a collection of objects attached to each key.
Documentation: Multimap_Is_Not_A_Map
First of all com.google.common.collect.Multimap is not java.util.Map, it is in a separate hierarchy.
Secondly, you can all the operations with Map<Integer, Set<String>> that Multimap interface requires but you will have to implement them yourself while HashMultimap offers ready implementation.
I have something along the lines of this:
public HashMap<Boolean, String> map = new HashMap();
map.put(this.inverted, "Inverted");
map.put(this.active, "Loading");
System.out.println(map.size());
after seeing that the size was always 1, I realised that using map.put was overriding the previous data. I am currently trying to iterate over the hashmap. Is there a way to add mappings to it without overriding previous ones?
You have declared your HashMap as: -
public HashMap<Boolean, String> map = new HashMap();
Now, just think how many maximum mapping can you have in your map? The answer you can get by thinking of, what all values can your Boolean type take. This is because, you cannot have duplicate keys in a HashMap.
So, probably you got it now, that you can at max have only 2 mappings in your map, one for true and other for false(In fact you can have a 3rd one too, as you can have a mapping for a null key too in your HashMap).
So, in your case, if both this.inverted and this.active are either true or false. Then only one of them can be there, and that would be the later value inserted.
Is there a way to add mappings to it without overriding previous ones?
Probably you have build your HashMap wrongly. You should declare your map as: -
private Map<String, Boolean> map = new HashMap();
And now you can put two mappings as: -
map.put("Inverted", this.inverted);
map.put("Loading", this.active);
It's because this.inverted.equals(this.active) and this.inverted.hashcode()==this.active.hashcode()
Maybe you need redefine the equals method for the key.
In MAP
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. ---> from Map Api
from your implementation, may be this.inverted and this.active both have same value.
Check the input once. print the keySet, then check.
or change the input to Map<String, Boolean>
As #Frank suggest you should invert your Map.
public final Map<String, Boolean> map = new HashMap<>();
map.put("Inverted", this.inverted);
map.put("Loading", this.active);
System.out.println(map);
If the keys are the same than the previous value is overwritten in a standard Java Map. If you don't want this, you can have a look at a multimap which is implemented for example in commons-collections. It can hold different values for one key.
Hashmap is based on key/value pairs. If your keys are equal (they have the same hashcode), it will behave as you described.
For your use case, reversing your key/value pairs will help you.
public HashMap<String, Boolean> map = new HashMap();
map.put("Inverted", this.inverted);
map.put("Loading", this.active);
System.out.println(map.size());
Get object of innermap ,by passing outer map key .. Then check if key of innermap exists then update values with previous data. else create new object of inner map.
I need to make an int array using Strings instead of ints.
EX: int["number2"] = 0; instead of int[2] = 0;
Does anyone know how to do this?
Thanks for your time.
you could use a HashMap - see here for more info!
Java doesn't support associative arrays, but you could use a HashMap:
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("key1", 25);
map.put("key2", 4589);
map.get("key1") will return 25.
You are not looking for an array but for an associative array.
In Java, in practice, every class that implements Map can be used as an associative container, since they can map keys to values (TreeMap<K,V>, HashMap<K,V>, and so on)
This syntax looks very like a map in Groovy, In Java, you could use something like a Map<String, Integer>.
Which data structure should i use to store and retrieve the following data?
(key1,val1)(key1,val2)(key1,val3)(key2,val4)(key2,val5)(key2,val6)(key3,val7)(key3,val8)(key3,val9)
Please help me.
Take a look at Google Guava's Multimap and its subtypes ListMultimap and SetMultimap.
From Multimap's javadoc: A collection similar to a Map, but which may associate multiple values with a
single key.
Map<Key, Collection<Value>> is the best approach
I don't know if it would work for you, but you may consider reversing key/value if values are unique and use a standard Map<ValueType, KeyType>
You can have a Map where values are collections like List/Set Depending on whether your pairs are distinct or not.
If you have distinct pairs you can go for something like Set interface:
Map<key, Set<value>>
Ex Map<key, HashSet<Value>>
If you do not have have distinct pairs((key1, val1), (key1, val1)) you can go for List interface:
Map<key, List<value>>
Map<key, ArrayList <Value>>
We can use MultiValueMap From Commons collections.
Reference :
http://commons.apache.org/proper/commons-collections/
Sample :
MultiValueMap map = new MultiValueMap();
map.put("SAN", 4);
map.put("SAN", 6);
map.put("TOM", 7);