Map<String, List<String>> myMaps = new HashMap<String, List<String>>();
    for (DataObject item : myList) {
        if (!myMaps.containsKey(item.getKey())) {
            myMaps.put(item.getKey(), new ArrayList<String>());
        }
        myMaps.get(item.getKey()).add(item.getValue());
    }
Answer from rius on Stack Overflow
Top answer
1 of 4
15

I believe something like this should work:

Map<String,List<String>> map =
    userList.stream()
            .flatMap(user -> {
                Map<String,String> um = new HashMap<>();
                um.put("names",user.getName());
                um.put("age",user.getAge());
                um.put("org",user.getOrg());
                return um.entrySet().stream();
            }) // produces a Stream<Map.Entry<String,String>>
            .collect(Collectors.groupingBy(Map.Entry::getKey,
                                           Collectors.mapping(Map.Entry::getValue,
                                                              Collectors.toList())));

It converts each User to a Map<String,String> (containing the 3 required properties indexed by the required keys), and then groups the entries of all the user maps by their keys.

EDIT:

Here's another alternative that creates the Map.Entrys directly instead of creating the small HashMaps, so it should be more efficient:

Map<String,List<String>> map =
    userList.stream()
            .flatMap (user -> Stream.of (new SimpleEntry<>("names",user.getName()),
                                         new SimpleEntry<>("age",user.getAge()),
                                         new SimpleEntry<>("org",user.getOrg())))
            .collect(Collectors.groupingBy(Map.Entry::getKey,
                                           Collectors.mapping(Map.Entry::getValue,
                                                              Collectors.toList())));
2 of 4
6

Eran's showed you how you can accomplish this with streams. As you can hopefully see, it's incredibly ugly.

If your issue with your procedural version is the amount of code duplication, there are other ways besides streams that we can use to solve that problem.

I would refactor the collection to its own method:

private static List<String> getProperty(List<User> users, Function<User, String> getter) {
    return users.stream().map(getter).collect(Collectors.toList());
}

Map<String,List<String>> map = new HashMap<>();
map.put("names", getProperty(userList, User::getName));
map.put("age",   getProperty(userList, User::getAge));
map.put("org",   getProperty(userList, User::getOrg));
🌐
Tabnine
tabnine.com › home page › code › java › java.util.map
How to use forEach method in java.util.Map
private StompHeaders(Map<String, List<String>> headers, boolean readOnly) { Assert.notNull(headers, "'headers' must not be null"); if (readOnly) { Map<String, List<String>> map = new LinkedMultiValueMap<>(headers.size()); headers.forEach((key, value) -> map.put(key, Collections.unmodifiableList(value))); this.headers = Collections.unmodifiableMap(map); } else { this.headers = headers; } } ... @SuppressWarnings({"unchecked", "rawtypes"}) private void merge(Map<String, Object> output, Map<String, Object> map) { map.forEach((key, value) -> { Object existing = output.get(key); if (value instanceof Map && existing instanceof Map) { // Inner cast required by Eclipse IDE.
🌐
Quora
quora.com › How-do-I-iterate-over-a-Map-String-ArrayList-Object
How to iterate over a Map<String, ArrayList<Object>> - Quora
Answer (1 of 5): [code java] for(Entry ent:map.entrySet()) { for(Object obj: Arrays.asList(ent.getValue())) { System.out.println(obj.toString()); } } [/code]
🌐
Coderanch
coderanch.com › t › 617033 › java › Map-elements-Map-List-String
How to get the Map elements while using Map<List<String>, List<String>> ? (Java in General forum at Coderanch)
Or if you are looking for advanced HashMap concepts then my tutorial can be helpful. In short you put into map key associated with value. When you want to get value by key provide key as argument of get(key) method. Note that key must be reference to the same object whose hashCode and equals ...
🌐
OneCompiler
onecompiler.com › java › 3urmp9w25
Convert List<Map<String,String>> to List<String> - Java - OneCompiler
Happy learning!"); } public static void main(String[] args) { hello(); } } Collection is a group of objects which can be represented as a single unit. Collections are introduced to bring a unified common interface to all the objects. Collection Framework was introduced since JDK 1.2 which is ...
Top answer
1 of 2
1

You should declare your map as:

Map<String, List<? extends Object>> myVehicles = 
                                new HashMap<String, List<? extends Object>>();

Map<String, List<Object>> wouldn't work, because you can't add a List<Bikes> where a List<Object> is needed, because generic types are invariant. A List<Bikes> is not a subclass of List<Object>, however it can be captured by a List<? extends Object>.

2 of 2
0

You can use the following code to declare:

Map<String, List<? extends Object>> objectsMap = new HashMap<String, List<? extends Object>>(); 

An example is as follows:

MapTest class ==>

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class MapTest {

public static void main(String[] args) {

    Map<String, List<? extends Object>> objectsMap = new HashMap<String, List<? extends Object>>();

    //Put String List into Map
    objectsMap.put("String", Arrays.asList("Hello","Java"));


    //Put Object List into Map
    objectsMap.put("Object", Arrays.asList(new Object(),new Object()));

    //Put Car List into Map
    objectsMap.put("Car", Arrays.asList(new Car("Band1"),new Car("Band2")));

    //Put Bike List into Map
    objectsMap.put("Bike", Arrays.asList(new Bike("Band1"),new Bike("Band2")));

}
}

Car class ==>

public class Car {

private String band;

public String getBand() {
    return band;
}

public Car(String band) {
    super();
    this.band = band;
}

public void setBand(String band) {
    this.band = band;
}
}

Bike class ==>

public class Bike {

private String band;

public String getBand() {
    return band;
}

public void setBand(String band) {
    this.band = band;
}

public Bike(String band) {
    super();
    this.band = band;
}

}
🌐
Baeldung
baeldung.com › home › java › java collections › java map › how to store hashmap inside a list
How to Store HashMap<String, ArrayList> Inside a List
April 3, 2025 - List<HashMap<String, List<String>>> booksAuthorsMapsList = new ArrayList<>(); Now, we have a List containing two HashMaps. To test it, we can put some books information in javaBookAuthorsMap and phpBooksAuthorsMap lists.
Find elsewhere
Top answer
1 of 2
6

You can accomplish this using Java 8 streams.

public List<Object> fetchMultiFieldsList() {
    return multiFieldMap.entrySet().stream()
      .flatMap(e -> {
          String entityName = e.getKey();
          List<Object> ids = e.getValue();
          return ids.stream()
            .map(id -> queryService.query(entityName, queryService.property("id").eq(id)));
      }).collect(Collectors.toList());
}

I think the code itself is relatively self-explanatory. The important bit is the usage of flatMap instead of map for the first mapping operation so that the resulting streams are concatenated, ending up with a flat list of objects rather than a list of lists.

It is unfortunate that Java does not support destructuring assignment, which would allow the first lambda expression to be a single expression of the form (k, v) -> ..., but it does not, so I've left the statements in for clarity.

If you are willing to omit the inner declarations, the above code can be simplified further.

public List<Object> fetchMultiFieldsList() {
    return multiFieldMap.entrySet().stream()
      .flatMap(e -> e.getValue().stream()
          .map(id -> queryService.query(e.getKey(), queryService.property("id").eq(id)))
      ).collect(Collectors.toList());
}

Whichever one you prefer is a matter of personal preference. The former has more descriptive variable names, while the latter is simpler and more functional.

2 of 2
1

You could replace the map with a multimap. Using Google's Guava Multimap, you don't need the nested loop / flatMap():

private Multimap<String, Object> multiFieldMap = ArrayListMultimap.create();

public List<Object> fetchMultiFieldsList() {
    return multiFieldMap.entries().stream()
        .map(e -> queryService.query(e.getKey(),
                      queryService.property("id").eq(e.getValue())))
        .collect(Collectors.toList());
}
🌐
Tabnine
tabnine.com › home page › code › java › java.util.map
How to use values method in java.util.Map
public Map<String, Object> defaultValues() { Map<String, Object> defaultValues = new HashMap<>(); for (ConfigKey key : configKeys.values()) { if (key.defaultValue != NO_DEFAULT_VALUE) defaultValues.put(key.name, key.defaultValue); } return ...
🌐
CopyProgramming
copyprogramming.com › howto › java-java-map-string-list-string-code-example
Java: Code Example: Mapping a List of Strings in Java Using Java Map
June 14, 2023 - Begin by denoting the items in the lists with Map<String,String> and obtaining a series of lists that contain maps. Afterward, use reduce to combine these lists into a singular list.
Top answer
1 of 4
4

You are trying to place a string where a map expects a List.

Instead of:

patientMap.put("PATIENTLIST", patientList);
patientMap.put("LASTKEY", date);

Place:

patientMap.put(date, patientList);

With a map where date string is key and list of patient is value you can quickly get a list of patients for a given date.


If you want to use a map to hold a date and list of objects in string form, then you would have to convert back those strings back to their original date or list of patient objects.

If this is really what you want I suggest you look into java object serialization and deserialization.

2 of 4
2

Here are the small changes which you can do to achieve above (Definitely you have to change the return type):

public Map<String, PatientMapObject> getPatients(String sendingApplication,String sendingFacility) {
    // TODO Auto-generated method stub
    Map<String, PatientMapObject> patientMap = null;
    List<PatientInfo> patientList = null;
    patientMap = new HashMap<String, PatientMapObject>();
    patientList = new ArrayList<PatientInfo>();
    try {

        PatientInfoDAO patientInfoDAO = new PatientInfoDAOImpl();
        ItemCollection<QueryOutcome> items = patientInfoDAO.getPatients(sendingApplication, sendingFacility);

       for(Item item : items){
            PatientInfo patient = new PatientInfo();

            patient.setAdministrativeSex("Male");

            patientList.add(patient);
        }

        String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

        PatientMapObject pmo = new PatientMapObject();
        pmo.setPatientList(patientList);
        pmo.setPDate(date);

        patientMap.put("PATIENTLIST", pmo);
        return patientMap;
    }catch(Exception ase){

        throw new RuntimeException("internalServerError");
    }
}

class PatientMapObject{


    private List<PatientInfo> patientList;
    private String pdate;

    public void setPDate(String pdate) {
        this.pdate = pdate; 
    }

    public void setPatientList(List<PatientInfo> patientList) {
        this.patientList = patientList;
    }

    //getters 
}
🌐
Vogella
vogella.com › tutorials › JavaCollections › article.html
Using Java lists and maps (Collections) - Tutorial
Before generics you had to cast ... an object of the wrong type into a collection you would create a runtime exception. The collection library support lambdas expressions. Operations on collections have been largely simplified with this. The following code shows an example how to create a Collection of type List which is parameterized with <String> to indicate to the Java compiler that ...
Top answer
1 of 5
35

Always try to use interface reference in Collection, this adds more flexibility.
What is the problem with the below code?

List<Map<String,List<String>>> list = new ArrayList<Map<String,List<String>>>();//This is the final list you need
Map<String, List<String>> map1 = new HashMap<String, List<String>>();//This is one instance of the  map you want to store in the above list.
List<String> arraylist1 = new ArrayList<String>();
arraylist1.add("Text1");//And so on..
map1.put("key1",arraylist1);
//And so on...
list.add(map1);//In this way you can add.

You can easily do it like the above.

2 of 5
16

First, let me fix a little bit your declaration:

List<Map<String, List<String>>> listOfMapOfList = 
    new HashList<Map<String, List<String>>>();

Please pay attention that I used concrete class (HashMap) only once. It is important to use interface where you can to be able to change the implementation later.

Now you want to add element to the list, don't you? But the element is a map, so you have to create it:

Map<String, List<String>> mapOfList = new HashMap<String, List<String>>();

Now you want to populate the map. Fortunately you can use utility that creates lists for you, otherwise you have to create list separately:

mapOfList.put("mykey", Arrays.asList("one", "two", "three"));

OK, now we are ready to add the map into the list:

listOfMapOfList.add(mapOfList);

BUT:

Stop creating complicated collections right now! Think about the future: you will probably have to change the internal map to something else or list to set etc. This will probably cause you to re-write significant parts of your code. Instead define class that contains you data and then add it to one-dimentional collection:

Let's call your class Student (just as example):

public Student {
    private String firstName;
    private String lastName;
    private int studentId;

    private Colectiuon<String> courseworks = Collections.emtpyList();

    //constructors, getters, setters etc
}

Now you can define simple collection:

Collection<Student> students = new ArrayList<Student>();

If in future you want to put your students into map where key is the studentId, do it:

Map<Integer, Student> students = new HashMap<Integer, Student>();
Top answer
1 of 1
2

Methods

The first thing that we can do is divide up the labor. Consider

void static main(String[] args) throws JsonProcessingException {
    Map<String, List<String>> properties = parseProperties(getPropertyValue());
    Map<String, Map<String, List<String>>> payload = buildPayload(properties);
    String json = new ObjectMapper().writeValueAsString(payload);
    System.out.println(json);
}

Now we have the heavy lifting in parseProperties and buildPayload.

I also hid the propertyValue in a method, but that was mostly to avoid obnoxious horizontal scrolling.

parseProperties

    String[] dayParts = propertyValue.split(",");

    for (String string : dayParts) {
      String[] array = string.split("  -  ");
      if (map.get(array[0]) == null) {
        List<String> list = new ArrayList<>();
        list.add(array[1]);
        map.put(array[0], list);
      } else {
        List<String> tempList = map.get(array[0]);
        tempList.add(array[1]);
        map.put(array[0], tempList);
      }
    }

Consider

    for (String string : propertyValue.split(",")) {
      String[] parts = string.split("  -  ");

      List<String> hours = map.get(parts[0]);
      if (hours == null) {
        hours = new ArrayList<>();
      }

      hours.add(parts[1]);
      map.put(parts[0], hours);
    }

We don't need a separate variable for the results of the comma split. We only use that for this loop, so we can do it directly.

We do need a separate variable for the parts of that string, as we use the parts separately. Also, we use one of them multiple times.

In both branches of the original if, we do two of the same commands. If we rewrite it this way, we can do those outside the if.

In the original if, we could have used contains, as we don't use the value otherwise. But this way, we save the result. If it is empty, we put an empty list there. Otherwise, we can just use the previous value.

buildPayload

    Map<String, Map<String, List<String>>> payload = new HashMap<>();
    Map<String, List<String>> hrs1 = new HashMap<>();
    hrs1.put("Hours", new ArrayList<String>());
    payload.put("Sunday", hrs1);
    payload.put("Monday", hrs1);
    payload.put("Tuesday", hrs1);
    payload.put("Wednesday", hrs1);
    payload.put("Thursday", hrs1);
    payload.put("Friday", hrs1);
    payload.put("Saturday", hrs1);
    for (Entry<String, List<String>> entry : map.entrySet()) {
      Map<String, List<String>> hrs = new HashMap<>();
      hrs.put("Hours", entry.getValue());
      if (payload.containsKey(entry.getKey())) {
        payload.put(entry.getKey(), hrs);
      }
    }

So you want to create a map with the seven days of the week. The same pattern can work here.

public static Map<String, List<String>> normalizeHours(Map<String, List<String>> hours) {
    if (hours == null) {
        hours = new HashMap<>();
        hours.put("Hours", new ArrayList<String>());
    }

    return hours;
}

And we'd use it like

    Map<String, Map<String, List<String>>> payload = new HashMap<>();
    payload.put("Sunday", normalizeHours(properties.get("Sunday")));
    payload.put("Monday", normalizeHours(properties.get("Monday")));
    payload.put("Tuesday", normalizeHours(properties.get("Tuesday")));
    payload.put("Wednesday", normalizeHours(properties.get("Wednesday")));
    payload.put("Thursday", normalizeHours(properties.get("Thursday")));
    payload.put("Friday", normalizeHours(properties.get("Friday")));
    payload.put("Saturday", normalizeHours(properties.get("Saturday")));

Instead of putting a dummy value into each day of the week and then replacing it, this puts the correct value in in the first place.

It's not shorter but is more reusable to have a container for the days of the week that you can use here.

    for (String dayOfTheWeek : dayNames) {
        payload.put(dayOfTheWeek, normalizeHours(properties.get(dayOfTheWeek)));
    }

It's not much longer even for this single problem. Once you have the container, it shortens the code.