我以为我会丢掉一些在Java中使用Map接口的实际示例,主要是因为仍然有很多旧资源不使用现代Java。 希望能帮助到你!

Create a map

Map<String, String> statesToCapitals = Map.of(
        "Washington", "Olympia",
        "Oregon", "Portland",
        "California", "Sacramento",
        "Idaho", "Boise",
        "Nevada", "Carson City",
        "Arizona", "Phoenix"
);

Map<String, String> statesToCapitals = Map.of(
        "Washington", "Olympia",
        "Oregon", "Portland",
        "California", "Sacramento",
        "Idaho", "Boise",
        "Nevada", "Carson City",
        "Arizona", "Phoenix"
);

请务必记住,以这种方式创建的地图是不可变的,并且null不能用作键!

这将创建一个地图,如下所示:

{Nevada=Carson City, California=Sacramento, Washington=Olympia, Idaho=Boise, Oregon=Portland, Arizona=Phoenix}

{Nevada=Carson City, California=Sacramento, Washington=Olympia, Idaho=Boise, Oregon=Portland, Arizona=Phoenix}

Iterate a map

statesToCapitals.forEach((key, value) -> {
    System.out.println("The capital of " + key + " is " + value);
});

statesToCapitals.forEach((key, value) -> {
    System.out.println("The capital of " + key + " is " + value);
});

这将输出:

The capital of Washington is Olympia
The capital of Idaho is Boise
The capital of Oregon is Portland
The capital of Arizona is Phoenix
The capital of Nevada is Carson City
The capital of California is Sacramento


The capital of Washington is Olympia
The capital of Idaho is Boise
The capital of Oregon is Portland
The capital of Arizona is Phoenix
The capital of Nevada is Carson City
The capital of California is Sacramento

Iterate Map entries

除了每次方法直接在地图上可用,该方法允许您传递要应用到其键和/或值的函数,还可以流式传输其条目并使用地图条目类。

例如,您可以打印条目:

capitals.entrySet().stream().forEach(System.out::println);

capitals.entrySet().stream().forEach(System.out::println);

这将输出:

Washington=Olympia
Idaho=Boise
Oregon=Portland
Arizona=Phoenix
Nevada=Carson City
California=Sacramento

Washington=Olympia
Idaho=Boise
Oregon=Portland
Arizona=Phoenix
Nevada=Carson City
California=Sacramento

Convert to a collection of the maps values

Collection<String> capitalCities = statesToCapitals.values();

Collection<String> capitalCities = statesToCapitals.values();

请注意,根据所使用的地图实现,您可以按未排序或已排序的顺序接收值。

所以你会有类似的东西:

[Sacramento, Carson City, Phoenix, Portland, Boise, Olympia]

[Sacramento, Carson City, Phoenix, Portland, Boise, Olympia]

Automatically retrieve a default value for missing entries

System.out.println("The capital of Wisconsin is " + statesToCapitals.getOrDefault("Wisconsin", "Don't know"));

System.out.println("The capital of Wisconsin is " + statesToCapitals.getOrDefault("Wisconsin", "Don't know"));

输出:

The capital of Wisconsin is Don't know

The capital of Wisconsin is Don't know


Convert from a collection of objects to a lookup map for those objects

假设您从代表美国州的State对象开始:

class State {
   public String name() { // ... etc

   public String capitalCity() { // ... etc
}

class State {
   public String name() { // ... etc

   public String capitalCity() { // ... etc
}

如果您拥有美国所有州的集合:

Collection<State> usStates = usStates();

Collection<State> usStates = usStates();

您可以创建一个地图,以按其名称查找每个州:

Map<String, State> nameToState = usStates.stream().collect(Collectors.toMap(State::name, Function.identity()));

Map<String, State> nameToState = usStates.stream().collect(Collectors.toMap(State::name, Function.identity()));

换句话说,您现在可以通过nameTo州.get(“加利福尼亚”)然后您将获得州与加利福尼亚有关。

Convert from a collection of objects to a lookup map on one of its values

假定与上面相同,但是这次,您想从州到首都—地图的键将是该对象的值,其名称如“ California”或“ Wisconsin”,并且该地图的值也将是 来自对象及其资本的值,例如“萨克拉门托”或“麦迪逊”。

Map<String, String> statesToCapitals = usStates.stream().collect(Collectors.toMap(State::name, State::capitalCity));

Map<String, String> statesToCapitals = usStates.stream().collect(Collectors.toMap(State::name, State::capitalCity));

Handling maps of lists

现在,让我们考虑State对象是否也能够返回该州所有主要城市的集合:

class State {
   public String name() { // ... etc

   public String capitalCity() { // ... etc

   public List<String> majorCities() { // ... etc
}

class State {
   public String name() { // ... etc

   public String capitalCity() { // ... etc

   public List<String> majorCities() { // ... etc
}

然后您创建了一个StatesToCities与上述类似的大写字母地图:

Map<String, List<String>> statesToCities = usStates.stream().collect(Collectors.toMap(State::name, State::majorCities));

Map<String, List<String>> statesToCities = usStates.stream().collect(Collectors.toMap(State::name, State::majorCities));

现在的区别是我们有一个Map<String, List<String>>而不是更简单Map<String, String>像我们以前一样。 地图的“值”是城市列表。 例如:

List<String> californiaCities = statesToCities.get("California");
System.out.println(californiaCities);
// outputs "[Sacramento, San Francisco, Los Angeles]"

List<String> californiaCities = statesToCities.get("California");
System.out.println(californiaCities);
// outputs "[Sacramento, San Francisco, Los Angeles]"

Add a value to the list in a Map of Lists

在“老式Java”中,您必须检查地图中是否存在键,以便您可以在列表不存在的情况下对其进行初始化:

// deprecated way of adding new values
Map<String, List<String>> statesToCities = statesAndCitiesMap();
if(!statesToCities.containsKey("Montana")) {
  statesToCities.put("Montana", new ArrayList<>());
}
statesToCities.get("Montana").add("Bozeman");

// deprecated way of adding new values
Map<String, List<String>> statesToCities = statesAndCitiesMap();
if(!statesToCities.containsKey("Montana")) {
  statesToCities.put("Montana", new ArrayList<>());
}
statesToCities.get("Montana").add("Bozeman");

现在您可以使用computeIfAbsent代替得到以确保您从初始的空列表开始,即使没有什么开头:

statesToCities.computeIfAbsent("Montana", initialValue -> new ArrayList<>()).add("Bozeman");

statesToCities.computeIfAbsent("Montana", initialValue -> new ArrayList<>()).add("Bozeman");

Create a count map

这是一个无时无刻不在发生的现实世界。 如果我们需要一张地图来统计集合中每种类型的事物的数量,该怎么办?

对于此示例,假设我们有一个带有品牌和型号的Phone类:

class Phone {
    public String brand() { // etc ...

    public String model() { // etc ...
}

class Phone {
    public String brand() { // etc ...

    public String model() { // etc ...
}

例如“ Apple iPhone 11”或“ Google Pixel 4”。

还有一系列电话,比方说亚马逊出售的所有电话:

Collection<Phone> phones = phonesOnAmazon();

Collection<Phone> phones = phonesOnAmazon();

然后我们将它们数起来:

Map<String, Long> numberOfPhonesPerBrand = phones.stream().collect(Collectors.groupingBy(Phone::brand, Collectors.counting()));

Map<String, Long> numberOfPhonesPerBrand = phones.stream().collect(Collectors.groupingBy(Phone::brand, Collectors.counting()));

困惑? 的分组收集器返回一个映射,其中第一个值作为键传递(电话::品牌),然后将传递的函数作为值进行计算。 在这种情况下,我们希望统计该品牌的每部手机,因此我们使用了Collectors。counting()。

由上面创建的地图在输出时如下所示:

{Google=2, Apple=2}

{Google=2, Apple=2}

Create a count map by summing up some value in each object

为了扩展前面的示例,让我们假设您想找出每个品牌每个给定时间亚马逊拥有多少手机。 我们不能只计算有多少部手机。 相反,对于本示例,我们必须使用可用数量的方法电话类,告诉我们目前亚马逊上有多少部电话。

Map<String, Integer> numOfPhonesPerBrand = phones.stream().collect(Collectors.groupingBy(Phone::brand, Collectors.summingInt(Phone::numberAvailable)));

Map<String, Integer> numOfPhonesPerBrand = phones.stream().collect(Collectors.groupingBy(Phone::brand, Collectors.summingInt(Phone::numberAvailable)));

此外summingInt,有收藏家叫总结长和summingDouble可以将分别返回long或double的方法的值相加。

Accumulate into a map of lists

假设您有一个清单电话对象,您想创建一个Map<串, List<电话>>代表品牌手机列表。 关键是串并且是品牌,例如“ Apple”或“ Samsung”。 地图值是List<串> and is just a list of phones such as for Apple it would be ["Apple i电话 11", "Apple i电话 11 Pro", etc..].

Map<String, List<Phone>> phoneListByBrand = phones.stream().collect(Collectors.groupingBy(Phone::brand));

Map<String, List<Phone>> phoneListByBrand = phones.stream().collect(Collectors.groupingBy(Phone::brand));

Sort Map entries

的地图条目类有许多自己的静态方法供地图操作使用。 例如,您可以在打印之前对地图进行排序:

phonesByBrand.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(System.out::println);

phonesByBrand.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(System.out::println);

这将输出:

Apple=[Apple iPhone 11, Apple iPhone 11 Pro]
Google=[Google Pixel 4, Google Pixel 4 XL]
Samsung=[Samsung Galaxy Note 10, Samsung Galaxy Fold]

Apple=[Apple iPhone 11, Apple iPhone 11 Pro]
Google=[Google Pixel 4, Google Pixel 4 XL]
Samsung=[Samsung Galaxy Note 10, Samsung Galaxy Fold]