我通过尝试不同的示例来学习Java 8流API。我试图使用流.map()方法从ArrayList形成HashMap。 (我知道.groupingBy方法,但是我试图理解流操作的底层逻辑。)当我运行代码而不调用forEach()方法(或任何终端操作)时,更改未应用于我的HashMap <>和它保持为空。但是调用终端操作可以保护我所做的更改。我当时认为终端操作仅用于返回非流值和结束流。谁能解释为什么会这样?
主类{
public static void main(String[] args) {
// Create a list of arrays then form a HasMap based on entries of list
List<String[]> list3 = new ArrayList<String[]>();
String[] entry1 = {"a","b","c"};
String[] entry2 = {"d","e","f"};
String[] entry3 = {"g","h","i"};
list3.add(entry1);
list3.add(entry2);
list3.add(entry3);
// hashmap
HashMap<String, String[]> map1 = new HashMap<String, String[]>();
// streamize the list to form hashmap
list3.stream()
.map(entry -> {
String key = entry[0];
String[] value = {entry[1],entry[2]};
map1.put(key, value);
// must return a String[]
return entry;
})
// CHANGES ARE ONLY APPLIED WHEN TERMINAL OPERATIONS CALLED ???
.forEach(entry -> {});
// print elements
for (Map.Entry<String,String[]> entry : map1.entrySet()) {
System.out.println(entry);
}
}
//没有终端操作
//Empty
//使用终端op
a = [Ljava.lang.String; @ 7921b0a2
d = [Ljava.lang.String; @ 174d20a
g = [Ljava.lang.String; @ 66d2e7d9
答案 0 :(得分:0)
我认为值得指出的是,您的HashMap
未填充的主要原因是因为您的代码已放入lambda expression的正文中。 Lambda类似于匿名内部类:
jbutton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
doSomething();
}
});
如果定义这样的内容,方法doSomething()
不会立即执行,相反,addActionListener
方法会将ActionListener
实例作为实例变量存储在某个地方,因此可以使用它后来。这意味着您实际上仅定义了一个方法,但尚未调用它。
map
接口的Stream
方法(无论您使用的是哪种实现)都接受Function
的实例,它只是一个定义。它仅将此Function
存储在某个位置,但不执行lambda表达式的主体。
Stream
实现很懒。在绝对没有必要之前,它的作用是不执行任何操作。只有当呼叫者实际上需要某些结果(即收集)时,这种情况才会出现。
调用终端操作后,然后 Stream实现实际上将应用所有必要的转换和过滤步骤,并返回某种形式的结果。
相关:
注意:流操作不应有副作用。这意味着您应该避免做类似map1.put(key, value)
的事情。