Java Collectors.toMap(): 将Stream收集到Map

IT 文章2年前 (2023)发布 小编
0 0 0

学习如何将Stream转换为Map,即使用Collectors.toMap()和Collectors.groupingBy()方法将Stream的项收集到Map中。

1.注意IllegalStateException

请注意,首先我们要知道Stream元素是否具有转Map后键字段的相同的情况,如果有的话,并且我们使用Collectors.toMap()方法,代码将抛出IllegalStateException。类似如下:[v_error]Exception in thread “main” java.lang.IllegalStateException:
Duplicate key 3 (attempted merging values Item[id=3, name=Item3] and Item[id=3, name=Item3])
at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:135)[/v_error]

2.将Stream转换为Map(无重复键)

在这种情况下,我们必须确保Stream中的每个键都是唯一的。处理完成后,我们将获得Map<K,V>,其中指定的键K仅与单个值V相关联。
为了演示目的,我们使用包含3个项目的Stream:

ad

程序员导航

优网导航旗下整合全网优质开发资源,一站式IT编程学习与工具大全网站

Stream<Item> stream = Stream.of(
  new Item(1, "Item1"),
  new Item(2, "Item2"),
  new Item(3, "Item3")
);

我们可以将上述Item实例的Stream转换为两种方式的Map<Long, String>:

  • Map键- Item ID
    Map值- Item Name。
Map<Long, String> mapWithValue = stream.collect(Collectors.toMap(Item::id, Item::name));
// {1=Item1, 2=Item2, 3=Item3}

在下一个示例中,我们使用Function.identity()将对象本身作为Map值来转换为Map<Long, Item>。

Map<Long, Item> map = stream.collect(Collectors.toMap(Item::id, Function.identity()));
// {1=Item[id=1, name=Item1], 2=Item[id=2, name=Item2], 3=Item[id=3, name=Item3]}

3. 将Stream转换为Map(有重复键)

如果流中有重复键的元素,有两种可能的方法来处理它:

  • 将所有值收集到List中并将它们与键关联起来
  • 仅选择一个值,并丢弃同一键的所有其他值

为了演示目的,我们使用包含五个元素的Stream,其中三个项目具有重复键’3’。

ad

AI 工具导航

优网导航旗下AI工具导航,精选全球千款优质 AI 工具集

Stream<Item> streamWithDuplicates = Stream.of(
  new Item(1, "Item1"),
  new Item(2, "Item2"),
  new Item(3, "Item3-1"),
  new Item(3, "Item3-2"),
  new Item(3, "Item3-3")
);

3.1将Stream收集到Map的List中

如果我们想将所有键的值存储在List中,我们可以使用Collectors.groupingBy()来收集元素,形成Map<key, List>的格式。在下面的示例中,我们将项目收集到Map的List中,即Map<K, List<Item>>。

Map<Long, List<Item>> mapWithList = streamWithDuplicates.collect(Collectors.groupingBy(Item::id));

程序输出:

{
	1=[Item[id=1, name=Item1]],
	2=[Item[id=2, name=Item2]],
	3=[
			Item[id=3, name=Item3-1],
			Item[id=3, name=Item3-2],
			Item[id=3, name=Item3-3]
		]
}

我们可以将该Stream转换为List包含Item名称的Map,即Map<K, List<String>>。

Map<Long, List<String>> mapWithGroupedValues = streamWithDuplicates
    .collect(
        Collectors.groupingBy(Item::id,
        Collectors.mapping(Item::name, Collectors.toList())));

程序输出:

{
	1=[Item1],
	2=[Item2],
	3=[Item3-1, Item3-2, Item3-3]
}

3.2. 将Stream收集到Map中并丢弃重复值

另一种方法是仅从多个值中选择一个值,并丢弃相同键的其他值。

在我们的示例中,我们可能决定选择Map键的最新名称,即item3-3,并丢弃其他值,即item3-1和item3-2。

ad

免费在线工具导航

优网导航旗下整合全网优质免费、免注册的在线工具导航大全

以下代码使用第三个参数mergeFunction,当遇到键上的冲突值时,它选择必须与键关联的值。

Map<Long, Item> mapWithGrouping = streamWithDuplicates
    .collect(Collectors.toMap(Item::id, Function.identity(), (oldValue, newValue) -> newValue));

程序输出:

{
	1=Item[id=1, name=Item1],
	2=Item[id=2, name=Item2],
	3=Item[id=3, name=Item3-3]
}

4.维持插入顺序或按键排序

有时,我们可能希望维护将键值对插入Map时的顺序。 LinkedHashMap维护这样的插入顺序,因此我们可以使用它来收集Stream项。

LinkedHashMap<Long, String> mapWithValueInInsertionOrder = stream
    .collect(Collectors.toMap(
    	Item::id,
    	Item::name,
    	(o, n) -> n,
    	LinkedHashMap::new));

同样,如果我们想应用并维护Map键的排序顺序,我们可以使用TreeMap。

TreeMap<Long, String> mapwithSortedKeys = stream
    .collect(Collectors.toMap(
    	Item::id,
    	Item::name,
    	(o, n) -> n,
    	TreeMap::new));

5. 结论

Java Stream教程讨论了将stream项收集到Map或List的多种方法。 我们看到了每种方法的示例及其输出,以便更好地了解每种方法对stream项的作用。

© 版权声明

相关文章

暂无评论

暂无评论...