如果其中一个值为'null' ,Java 8 Collectors.toMap
将抛出一个NullPointerException
.我不明白这种行为,map可以包含null指针作为值而没有任何问题.有没有一个很好的理由为什么值不能为空Collectors.toMap
?
另外,是否有一个很好的Java 8方法来修复它,或者我应该恢复到普通的旧循环?
我的问题的一个例子:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Answer {
private int id;
private Boolean answer;
Answer() {
}
Answer(int id, Boolean answer) {
this.id = id;
this.answer = answer;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Boolean getAnswer() {
return answer;
}
public void setAnswer(Boolean answer) {
this.answer = answer;
}
}
public class Main …
Run Code Online (Sandbox Code Playgroud) 我知道如何List
从Y
- > "转换"一个简单的Java Z
,即:
List<String> x;
List<Integer> y = x.stream()
.map(s -> Integer.parseInt(s))
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
现在我想用Map做基本相同的事情,即:
INPUT:
{
"key1" -> "41", // "41" and "42"
"key2" -> "42 // are Strings
}
OUTPUT:
{
"key1" -> 41, // 41 and 42
"key2" -> 42 // are Integers
}
Run Code Online (Sandbox Code Playgroud)
解决方案不应限于String
- > Integer
.就像List
上面的例子一样,我想调用任何方法(或构造函数).
收集器的Javadoc显示如何将流的元素收集到新的List中.是否有一个单行程序将结果添加到现有的ArrayList中?
Collectors.toSet()
不保留秩序.我可以使用Lists代替,但我想指出结果集合不允许元素重复,这正是Set
接口的用途.
我有这个清单(List<String>
):
["a", "b", null, "c", null, "d", "e"]
Run Code Online (Sandbox Code Playgroud)
我想要这样的事情:
[["a", "b"], ["c"], ["d", "e"]]
Run Code Online (Sandbox Code Playgroud)
换句话说,我想使用null
值作为分隔符将我的列表拆分为子列表,以获取列表列表(List<List<String>>
).我在寻找Java 8解决方案.我尝试过,Collectors.partitioningBy
但我不确定这是我在寻找什么.谢谢!
我正在使用Java 8 lambdas并希望Collectors
toMap
用来返回一个SortedMap
.我能想出的最好的是调用下面Collectors
toMap
用假设法mergeFunction
和mapSupplier
等于TreeMap::new
.
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier) {
BiConsumer<M, T> accumulator = (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
Run Code Online (Sandbox Code Playgroud)
我不想传递合并函数,正如我想要throwingMerger()
的那样,与基本toMap
实现相同,如下所示:
public static <T, K, U>
Collector<T, ?, Map<K, U>> toMap(Function<? …
Run Code Online (Sandbox Code Playgroud) 采取以下示例代码行:
Set<String> someSet = someColletion.stream().map(p -> p.toString()).collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)
我想要一个HashSet
.把调试器带到代码中,我确实得到了一个HashSet
.我看了看java.util.stream.Collectors.toSet()
下面的代码:
public static <T> Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> { left.addAll(right); return left; },
CH_UNORDERED_ID);
}
Run Code Online (Sandbox Code Playgroud)
合同保证 a Set
,实施决定a HashSet
; 看似合理.但是,我的实现需要由a保证的恒定时间查找HashSet
,而不仅仅是任何旧的查找Set
.如果执行toSet()
决定使用say a FooSet
,这完全在其权利范围内,那么我的实现就会受到影响.
这个问题的最佳实践解决方案是什么?
我正在阅读Lambda:Libraries Edition的状态,我对一个声明感到惊讶:
在Streams部分下,有以下内容:
List<Shape> blue = shapes.stream()
.filter(s -> s.getColor() == BLUE)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
该文件没有说明shapes
实际是什么,我不知道它是否重要.
令我困惑的是:List
这段代码返回了什么样的具体内容?
List<Shape>
,这是完全正常的.stream()
也filter()
决定使用哪种列表.Collectors.toList()
既没有指定具体的类型List
.那么,这里使用的具体类型(子类)List
是什么?有保证吗?
让我们考虑一个hashmap
Map<Integer, List> id1 = new HashMap<Integer,List>();
Run Code Online (Sandbox Code Playgroud)
我在两个hashmap中都插入了一些值.
例如,
List<String> list1 = new ArrayList<String>();
list1.add("r1");
list1.add("r4");
List<String> list2 = new ArrayList<String>();
list2.add("r2");
list2.add("r5");
List<String> list3 = new ArrayList<String>();
list3.add("r3");
list3.add("r6");
id1.put(1,list1);
id1.put(2,list2);
id1.put(3,list3);
id1.put(10,list2);
id1.put(15,list3);
Run Code Online (Sandbox Code Playgroud)
Q1)现在我想对hashmap中的键应用过滤条件并检索相应的值(List).
例如:这里我的查询是key = 1,输出应该是'list1'
我写
id1.entrySet().stream().filter( e -> e.getKey() == 1);
Run Code Online (Sandbox Code Playgroud)
但我不知道如何检索列表作为此流操作的输出.
Q2)我想再次对hashmap中的键应用过滤条件并检索相应的列表列表.
例如:这里我的查询是key = 1%(即键可以是1,10,15),输出应该是'list1','list2','list3'(列表列表).
在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)是否有另一种更简单的方法来接受一个空键,而不必创建我自己的收集器?