6

I have a List of strings which are actually keys and values: "key1", "value1", "key2", "value2", ... (every odd item is a key, every even — value). How can I convert it to Map like this "key1" -> "value1", "key2" -> "value2", ... in a beautiful way?

5 Answers 5

7

You can simply do:

Iterator<String> it = list.iterator();
while(it.hasNext()) {
    map.put(it.next(), it.next());
}

This will be more efficient than using the get(index) method (in case the list implementation does not allow random access)

Sign up to request clarification or add additional context in comments.

2 Comments

This throws an exception if the list is "key1", "value1", "key2", i.e. non even length.
@Tunaki Yes, having the list well formed is a prerequisite. Checks can easily be added but it is not really the point of the answer. I don't think it deserves a downvote though...
7

Here's a relatively neat way:

var map = IntStream.range(0, list.size() / 2).boxed()
    .collect(Collectors.toMap(i -> list.get(i * 2), i -> list.get(i * 2 + 1)));

Comments

6

If your list has random access, like an ArrayList, the straight-forward way is to loop over the elements in the list with a step of 2:

public static void main(String[] args) {
    List<String> list = Arrays.asList("key1", "value1", "key2", "value2");

    Map<String, String> map = new HashMap<>();
    for (int i = 0; i < list.size() - 1; i += 2) {
        map.put(list.get(i), list.get(i + 1));
    }

    System.out.println(map);
}

Note that this also handles correctly the case where the list doesn't have an even length. It will ignore the last element. For example, if the list is "key1", "value1", "key2", the output will be the map {key1=value1}.

2 Comments

I was wondering, do you think it would be possible using Java8 streams?
@YassinHajaj sprinter answered with one already :) stackoverflow.com/a/36087498/1743880
4

With Eclipse Collections the following should work:

MutableList<String> list = 
    Lists.mutable.of("key1", "value1", "key2", "value2", "key3", "value3");
Map<String, String> map = 
    list.asLazy().chunk(2).toMap(Iterate::getFirst, Iterate::getLast);

Verify.assertMapsEqual(
    Maps.mutable.of("key1", "value1", "key2", "value2", "key3", "value3"), map);

MutableList is an Eclipse Collections list interface. If you have a JDK list, following should work:

List<String> list = 
    Arrays.asList("key1", "value1", "key2", "value2", "key3", "value3");
Map<String, String> map =
    ListAdapter.adapt(list).asLazy().chunk(2).toMap(Iterate::getFirst, Iterate::getLast);

Verify.assertMapsEqual(
    Maps.mutable.of("key1", "value1", "key2", "value2", "key3", "value3"), map);

The above uses chunk which generates intermediate lists. The code will succeed with a list with an odd number of elements, but the resulting map will have one entry where the key and value are the same. This code works with both random access and non-random access lists.

The code below may be more efficient for random access lists.

MutableList<String> list = 
    Lists.mutable.of("key1", "value1", "key2", "value2", "key3", "value3");
MutableMap<String, String> map = Maps.mutable.empty();
IntInterval.oneToBy(list.size(), 2).each(i -> map.put(list.get(i - 1), list.get(i)));

Verify.assertMapsEqual(
    Maps.mutable.of("key1", "value1", "key2", "value2", "key3", "value3"), map);

Note: I am a contributor to Eclipse Collections.

Comments

1

I'm not sure there's a "beautiful" way, but this is the simplest way:

while (!list.isEmpty()) {
    map.put(list.remove() ,list.remove());
}

2 Comments

I think you need:.remove(0), I would also check if list.size()%2 == 0
This is risky because it mutates the list, which might throw an exception.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.