如何在Java中将两个数组映射到一个HashMap?

14

我有两个字符串数组。其中一个包含缩写名称。

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

另一个有很长的名字。

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

两个具有相同元素数量的集合,如何将短名称映射为KEY,将长名称映射为HashMap中的VALUE?

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

我知道可以通过循环完成。有更好的方法吗?


我认为在这种情况下循环是最好的方式——当这两个数组的大小相同时。 - Razib
为什么首先要在数组中存储? - Nitin Dandriyal
3个回答

36

你有很多方法可以做到这一点。其中一个相当容易理解和应用的方法是使用Java 8流和收集器,将索引流映射为键值对:

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

有一些第三方Java库包括一个“zip”函数,用于获取两个流并从一个流到另一个流生成映射。但实际上,它们只是以更整洁的方式实现了与上述代码相同的操作。


Java 7及以下的版本呢? - Sindhoo Oad
@10sw33 在Java 8之前(除了升级之外!),你仍然有一些选择。可以使用第三方库或使用Arrays.toList(shortNames).forEach来遍历一个数组中的所有项并添加映射条目。我知道这实际上只是另一种形式的迭代,但流也是如此! - sprinter
@sprinter 很好的回答,但正如Jens在下面所说的那样,他需要boxed()。 - Nick Ziebert

3
你可以使用org.apache.commons.lang3.ArrayUtils
以下是一个例子:
Map colorMap = ArrayUtils.toMap(new String[][] {
    {"RED", "#FF0000"},
    {"GREEN", "#00FF00"},
    {"BLUE", "#0000FF"}});

3

对我而言,采纳的答案并没有起作用,因为IntStream没有提供一个参数的collect方法。

不过,你仍然可以从toMap收集器中受益,只需先将int原始类型的值装箱成Integer对象。如果你想保留元素顺序,请使用toMap的扩展版本,再加上LinkedHashMap::new,就像下面展示的那样:

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);
    }
}

参见:为什么原始流没有collect(Collector)?

我该如何在对哈希映射进行排序时按降序/升序进行操作? - ColstonBod-oy
1
@ColstonBod-oy 你可以在 .collect(...) 前添加 .sorted(Comparator.comparing(i -> shortNames[i]))。如果这不起作用,最好提出一个新问题。 - Jens Piegsa
是的!它可以工作,我如何实现降序呢? - ColstonBod-oy
1
.sorted(Comparator.comparing(i -> shortNames[i], Comparator.reverseOrder())) @ColstonBod-oy - Jens Piegsa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接