14

I have two String arrays. One having short name.

// days short name
String[] shortNames = {"SUN", "MON", "...", "SAT"};

The other having long name.

// days long name
String[] longNames = {"SUNDAY", "MONDAY", "....", "SATURDAY"};

Both having same number of elements. How can I map short name as KEY and long name as VALUE in HashMap?

HashMap<String, String> days = new HashMap<>();

I know, I can make by looping. Is there a better way?

Madan Sapkota
  • 25,047
  • 11
  • 113
  • 117

3 Answers3

35

There are lots of ways you can do this. One that is fairly easy to understand and apply is using Java 8 streams and collectors to map from a stream of indices to key value pairs:

Map<String, String> days = IntStream.range(0, shortNames.length).boxed()
    .collect(Collectors.toMap(i -> shortNames[i], i -> longNames[i]));

There are some third party Java libraries that include a 'zip' function to take two streams and produce a map from one to the other. But really they are just neater ways of achieving the same thing as the code above.

sprinter
  • 27,148
  • 6
  • 47
  • 78
  • and what about java 7 and below? – Sindhoo Oad May 20 '15 at 04:54
  • @10sw33 Below Java 8 (other than upgrading!) you still have a few options. Use a third party library or use `Arrays.toList(shortNames).forEach` to go through all the items in one array and add the map entries. I know this is really just iteration by another name but then so also are streams! – sprinter May 20 '15 at 05:09
  • @sprinter Good answer, but he needs boxed() as Jens said below. – Nick Ziebert Mar 26 '17 at 01:49
3

The accepted answer did not work for me, as the IntStream does not provide a one-argument collect method.

To nevertheless benefit from the toMap collector you have to box the int primitives into Integer objects first. If you like to preserve the element order, use the extended version of toMap together with LinkedHashMap::new like shown below:

package learning.java8;

import static java.util.stream.Collectors.*;
import static org.junit.Assert.*;

import java.time.DayOfWeek;
import java.time.format.TextStyle;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.stream.IntStream;

import org.junit.Test;

public class IntStreamLT {

    @Test
    public void q30339679() {

        final String[] shortNames = getDayOfWeekNamesInEnglish(TextStyle.SHORT);
        final String[] longNames = getDayOfWeekNamesInEnglish(TextStyle.FULL);

        final Map<String, String> days = IntStream.range(0, shortNames.length).boxed()
                .collect(toMap(i -> shortNames[i], i -> longNames[i]));

        System.out.println(days);

        final Map<String, String> sorted = IntStream.range(0, shortNames.length).boxed()
                .collect(toMap(
                        i -> shortNames[i], i -> longNames[i],
                        (i, j) -> i, LinkedHashMap::new));

        System.out.println(sorted);

        assertEquals("{Mon=Monday, Tue=Tuesday, Wed=Wednesday, Thu=Thursday, "
                + "Fri=Friday, Sat=Saturday, Sun=Sunday}", sorted.toString());
    }

    private static String[] getDayOfWeekNamesInEnglish(final TextStyle style) {

        return Arrays.stream(DayOfWeek.values())
                .map(day -> day.getDisplayName(style, Locale.ENGLISH))
                .toArray(String[]::new);
    }
}

see also: Why don't primitive Stream have collect(Collector)?

Community
  • 1
  • 1
Jens Piegsa
  • 7,399
  • 5
  • 58
  • 106
3

You can use org.apache.commons.lang3.ArrayUtils.

Here is an example:

Map colorMap = ArrayUtils.toMap(new String[][] {
    {"RED", "#FF0000"},
    {"GREEN", "#00FF00"},
    {"BLUE", "#0000FF"}});
Eugene Berdnikov
  • 2,150
  • 2
  • 23
  • 30
alex
  • 39
  • 1