How to convert a Java List to Map efficiently?

I recently discussed with a colleague about the optimal way to convert a Java List to Map and whether there are specific benefits to doing so.

Is the following approach considered efficient, or is there a better way?

List<Object[]> results;
Map<Integer, String> resultsMap = new HashMap<>();
for (Object[] o : results) {
    resultsMap.put((Integer) o[0], (String) o[1]);
}

I’d appreciate any guidance on the best practices for this conversion.

I’ve worked with this kind of task quite a bit, and honestly, your approach looks pretty solid for straightforward cases! Using a simple for-loop is great for readability and keeping things clear. Here’s a tiny enhancement I’d make just to ensure you’re handling edge cases a little more gracefully:

Map<Integer, String> resultsMap = new HashMap<>();
for (Object[] entry : results) {
    if (entry.length >= 2 && entry[0] instanceof Integer && entry[1] instanceof String) {
        resultsMap.put((Integer) entry[0], (String) entry[1]);
    }
}

Adding checks like this helps avoid ClassCastException in case the data isn’t exactly what you expect, which can be really helpful when dealing with raw or untrusted data. Plus, it makes sure you only add valid entries to the map. It’s a solid, no-frills way to go about converting a java list to map, especially for smaller or less performance-sensitive applications.

I see your point about the for-loop being reliable, but if you’re open to a more modern Java approach, I’d suggest using Java 8 Streams. I’ve found this approach much cleaner and more expressive for handling such conversions. Here’s how I would tackle the java list to map conversion:

Map<Integer, String> resultsMap = results.stream()
    .filter(o -> o.length >= 2 && o[0] instanceof Integer && o[1] instanceof String)
    .collect(Collectors.toMap(o -> (Integer) o[0], o -> (String) o[1]));

This is concise, functional, and a lot more readable in my opinion. It also has the benefit of clearly separating logic—no need for explicit loops. One thing to note: Collectors.toMap() will throw an exception if duplicate keys exist, which is great for avoiding silent errors, but if you expect duplicates, you can easily provide a merge function to handle them. It’s a perfect approach for those who prefer declarative programming when converting a java list to map.

You’re spot on with the stream approach, but if you’re working with large data sets or need performance in a multi-threaded context, I’d recommend using parallel streams. I’ve seen great improvements in speed for big lists, especially when you can leverage multiple cores in a multi-threaded environment. Here’s a modified version for java list to map conversion:

Map<Integer, String> resultsMap = results.parallelStream()
    .filter(o -> o.length >= 2 && o[0] instanceof Integer && o[1] instanceof String)
    .collect(Collectors.toConcurrentMap(o -> (Integer) o[0], o -> (String) o[1], (existing, replacement) -> existing));

The parallelStream() taps into multi-core processors, and toConcurrentMap() ensures thread safety, making it great for concurrent processing. The merge function (existing, replacement) -> existing prevents overwriting values when duplicates occur, ensuring the integrity of the data. It’s a really efficient way to handle large data conversions and can make a significant performance difference when dealing with massive datasets while converting a java list to map. Just keep in mind that parallel streams can add overhead in smaller datasets, so it’s worth considering the size before deciding.