Mar*_*rcG 39 java hashmap java-8 java-stream collectors
在Java 8中,这适用于:
Stream<Class> stream = Stream.of(ArrayList.class);
HashMap<Class, List<Class>> map = (HashMap)stream.collect(Collectors.groupingBy(Class::getSuperclass));
Run Code Online (Sandbox Code Playgroud)
但这不是:
Stream<Class> stream = Stream.of(List.class);
HashMap<Class, List<Class>> map = (HashMap)stream.collect(Collectors.groupingBy(Class::getSuperclass));
Run Code Online (Sandbox Code Playgroud)
Maps允许null键,List.class.getSuperclass()返回null.但Collectors.grouping可以在Collectors.java第907行发出NPE:
K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
Run Code Online (Sandbox Code Playgroud)
如果我创建自己的收集器,它的工作原理改为:
K key = classifier.apply(t);
Run Code Online (Sandbox Code Playgroud)
我的问题是:
1)Collectors的Javadoc.GroupingBy并没有说它不应该映射一个空键.出于某种原因这种行为是否必要?
2)是否有另一种更简单的方法来接受一个空键,而不必创建我自己的收集器?
小智 44
我遇到了同样的问题.这失败了,因为groupingBy对分类器返回的值执行Objects.requireNonNull:
Map<Long, List<ClaimEvent>> map = events.stream()
.filter(event -> eventTypeIds.contains(event.getClaimEventTypeId()))
.collect(groupingBy(ClaimEvent::getSubprocessId));
Run Code Online (Sandbox Code Playgroud)
使用Optional,这有效:
Map<Optional<Long>, List<ClaimEvent>> map = events.stream()
.filter(event -> eventTypeIds.contains(event.getClaimEventTypeId()))
.collect(groupingBy(event -> Optional.ofNullable(event.getSubprocessId())));
Run Code Online (Sandbox Code Playgroud)
Mar*_*rcG 11
对于第一个问题,我同意skiwi它不应该抛出一个NPE.我希望他们会改变它(或者至少将它添加到javadoc).同时,为了回答第二个问题,我决定使用Collectors.toMap而不是Collectors.groupingBy:
Stream<Class<?>> stream = Stream.of(ArrayList.class);
Map<Class<?>, List<Class<?>>> map = stream.collect(
Collectors.toMap(
Class::getSuperclass,
Collections::singletonList,
(List<Class<?>> oldList, List<Class<?>> newEl) -> {
List<Class<?>> newList = new ArrayList<>(oldList.size() + 1);
newList.addAll(oldList);
newList.addAll(newEl);
return newList;
}));
Run Code Online (Sandbox Code Playgroud)
或者,封装它:
/** Like Collectors.groupingBy, but accepts null keys. */
public static <T, A> Collector<T, ?, Map<A, List<T>>>
groupingBy_WithNullKeys(Function<? super T, ? extends A> classifier) {
return Collectors.toMap(
classifier,
Collections::singletonList,
(List<T> oldList, List<T> newEl) -> {
List<T> newList = new ArrayList<>(oldList.size() + 1);
newList.addAll(oldList);
newList.addAll(newEl);
return newList;
});
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
Stream<Class<?>> stream = Stream.of(ArrayList.class);
Map<Class<?>, List<Class<?>>> map = stream.collect(groupingBy_WithNullKeys(Class::getSuperclass));
Run Code Online (Sandbox Code Playgroud)
请注意rolfl给出了另一个更复杂的答案,它允许您指定自己的地图和列表供应商.我没有测试过.
在groupingBy之前过滤掉空实例。
这是一个例子MyObjectlist.stream().filter(p -> p.getSomeInstance() != null).collect(Collectors.groupingBy(MyObject::getSomeInstance));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22632 次 |
| 最近记录: |