HashMap: One Key, multiple Values
Libraries exist to do this, but the simplest plain Java way is to create a Map
of List
like this:
Map<Object,ArrayList<Object>> multiMap = new HashMap<>();
HashMap with multiple values under the same key
You could:
- Use a map that has a list as the value.
Map<KeyType, List<ValueType>>
. - Create a new wrapper class and place instances of this wrapper in the map.
Map<KeyType, WrapperType>
. - Use a tuple like class (saves creating lots of wrappers).
Map<KeyType, Tuple<Value1Type, Value2Type>>
. - Use mulitple maps side-by-side.
Examples
1. Map with list as the value
// create our map
Map<String, List<Person>> peopleByForename = new HashMap<>();
// populate it
List<Person> people = new ArrayList<>();
people.add(new Person("Bob Smith"));
people.add(new Person("Bob Jones"));
peopleByForename.put("Bob", people);
// read from it
List<Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs[0];
Person bob2 = bobs[1];
The disadvantage with this approach is that the list is not bound to exactly two values.
2. Using wrapper class
// define our wrapper
class Wrapper {
public Wrapper(Person person1, Person person2) {
this.person1 = person1;
this.person2 = person2;
}
public Person getPerson1() { return this.person1; }
public Person getPerson2() { return this.person2; }
private Person person1;
private Person person2;
}
// create our map
Map<String, Wrapper> peopleByForename = new HashMap<>();
// populate it
peopleByForename.put("Bob", new Wrapper(new Person("Bob Smith"),
new Person("Bob Jones"));
// read from it
Wrapper bobs = peopleByForename.get("Bob");
Person bob1 = bobs.getPerson1();
Person bob2 = bobs.getPerson2();
The disadvantage to this approach is that you have to write a lot of boiler-plate code for all of these very simple container classes.
3. Using a tuple
// you'll have to write or download a Tuple class in Java, (.NET ships with one)
// create our map
Map<String, Tuple2<Person, Person> peopleByForename = new HashMap<>();
// populate it
peopleByForename.put("Bob", new Tuple2(new Person("Bob Smith",
new Person("Bob Jones"));
// read from it
Tuple<Person, Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs.Item1;
Person bob2 = bobs.Item2;
This is the best solution in my opinion.
4. Multiple maps
// create our maps
Map<String, Person> firstPersonByForename = new HashMap<>();
Map<String, Person> secondPersonByForename = new HashMap<>();
// populate them
firstPersonByForename.put("Bob", new Person("Bob Smith"));
secondPersonByForename.put("Bob", new Person("Bob Jones"));
// read from them
Person bob1 = firstPersonByForename["Bob"];
Person bob2 = secondPersonByForename["Bob"];
The disadvantage of this solution is that it's not obvious that the two maps are related, a programmatic error could see the two maps get out of sync.
how to add multiple values to single key in java
Since Map<K,V>
maps one key to one value, you need V
to be of type List<T>
:
Map<String,List<Integer>> multiMap = new HashMap<>();
One consequence of having a type like that is that now the process of adding an item to a key consists of two steps: you must check if the list for the key exists, and then either add a new item to an existing list, or add a new list with a single item:
List<Integer> current = multiMap.get(key);
if (current == null) {
current = new ArrayList<Integer>();
multiMap.put(key, current);
}
current.add(val);
If you use Java 8, you can use computeIfAbsent
to greatly simplify the code:
multiMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
Java HashMap : How to add multiple values to one key?
Do not reuse the same reference of ArrayList
. Create new ArrayList<Object[]>();
and add line
to it. Do it as follows:
List result = dao.getServiceParam();
HashMap<Long,List<Object[]>> mapArray = new HashMap<Long, List<Object[]>>();
List<Object[]> listObj = null;
Object[] line = null, nextLine = null;
Long id = Long.valueOf(0), nextId = Long.valueOf(0);
if(!result.isEmpty()) {
for (int i=0; i< result.size(); i++) {
listObj = new ArrayList<Object[]>();
do{
line = (Object[])result.get(i);
if ((BigDecimal) line[0]!=null) {
listObj.add(line);
id = new Long(((BigDecimal) line[0]).longValue());
}
i++;
if(i<result.size()){
nextLine = (Object[])result.get(i);
if ((BigDecimal) nextLine[0]!=null) {
nextId = new Long(((BigDecimal) nextLine[0]).longValue());
}
}
}while(id.equals(nextId));
mapArray.put(id, listObj);
i--;
}
}
Feel free to comment in case of any doubt/issue.
Java HashMap, One key multiple Values, One map
To post my comment as an answer: use a Map<String, List<ToA>>
like this:
Map<String, List<ToA>> wordkey = new HashMap<>();
ToA a = new ToA("Doolin", "Bill", "18580824-1464");
ToA b = new ToA("Dalton", "Bob", "18701005-2232");
ToA c = new ToA("James", "Jesse", "18470905-2401");
ToA d = new ToA("Dalton", "Emmet", "18710713-0818");
wordkey.put("Doolin", Arrays.asList(a));
wordkey.put("James", Arrays.asList(c));
wordkey.put("Dalton", Arrays.asList(b, d));
To print the names based on the input, you can do something like this:
System.out.println("Efternamn:");
name = scan.next();
List<ToA> toas = wordkey.get(name);
if (toas != null) {
System.out.println("ToAs");
for (ToA toa : toas) {
System.out.println("ToA: " + toa);
}
}
else {
System.out.println("No ToAs found for input: " + name);
}
Concurrent Map with one key and multiple values
tl;dr
personFavoriteColors.computeIfAbsent(
"Alice" ,
( x -> new CopyOnWriteArrayList<>() )
)
.add( "Purple" )
;
personFavoriteColors.computeIfAbsent(
"Alice" ,
( x -> new CopyOnWriteArrayList<>() )
)
.add( "Gold" )
;
personFavoriteColors.toString(): [Purple, Gold]
Map::computeIfAbsent
Java now has multimap behavior built-in with new computeIfAbsent
method defined on the Map
interface.
Define your map.
ConcurrentMap< String , Set< String> > personFavoriteColors = new ConcurrentSkipListMap<>() ;
We are using a Map
implementation that implements the ConcurrentMap
interface for thread-safety as you requested. Java offers two such implementations.
Use a single line to create a new list or set to hold the multiple values.
personFavoriteColors.computeIfAbsent(
"Alice" ,
( x -> new CopyOnWriteArraySet<>() ) // Lambda expression. Run only if needed to run (if absent).
) // Returns the value of a map (a `Set` or `List` when desiring a multimap).
.add( "Purple" )
;
You may access the Set
(or List
) outside of the Map
that owns it. So that Set
(or List
) must also be concurrent.
Here we used a concurrent set, CopyOnWriteArraySet
as our value for the map.
For example:
Set< String > favoriteColorsForAlice = personFavoriteColors.get( "Alice" ) ;
System.out.println( favoriteColorsForAlice ) ;
See this code run live on IdeOne.com.
[Purple, Gold]
Related Topics
How to Terminate Scanner When Input Is Complete
Comparing Two Integer Arrays in Java
How to Switch JPAnels Inside a Jframe
Execute Another Jar in a Java Program
Nullpointerexception in Java with No Stacktrace
Java: (String[])List.Toarray() Gives Classcastexception
Integrating Tomcat and Eclipse as a Hot-Deploy Environment
Convert Existing Eclipse Project to Maven Project
How to Delete Stuff Printed to Console by System.Out.Println()
Calculating Distance Between Two Points, Using Latitude Longitude
Java 1.6 - Determine Symbolic Links
Java Embedded Databases Comparison
Good Way to Encapsulate Integer.Parseint()
Get Domain Name from Given Url
Android "Gps Requires Access_Fine_Location" Error, Even Though My Manifest File Contains This