java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
所有的 Collection 集合都可以通过 stream 默认方法获取流;
Stream 接口的静态方法 of 可以获取数组对应的流。
根据Collection获取流
import java.util.*; import java.util.stream.Stream; public class Demo04GetStream { public static void main(String[] args) { List<String> list = new ArrayList<>(); // ... Stream<String> stream1 = list.stream(); Set<String> set = new HashSet<>(); // ... Stream<String> stream2 = set.stream(); Vector<String> vector = new Vector<>(); // ...
Stream<String> stream3 = vector.stream();
}
}
根据Map获取流 import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; public class Demo05GetStream { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); // ... Stream<String> keyStream = map.keySet().stream(); Stream<String> valueStream = map.values().stream(); Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream(); } }
根据数组获取流 如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以 Stream 接口中提供了静态方法 of ,使用很简单: import java.util.stream.Stream; public class Demo06GetStream { public static void main(String[] args) { String[] array = { "张无忌", "张翠山", "张三丰", "张一元" }; Stream<String> stream = Stream.of(array); }
流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:
延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方
法均为延迟方法。)
终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调
用。本小节中,终结方法包括 count 和 forEach 方法。
逐一处理 void forEach(Consumer<? super T> action); 过滤 Stream<T> filter(Predicate<? super T> predicate); 映射 <R> Stream<R> map(Function<? super T, ? extends R> mapper); 统计个数 long count(); 取用前几个 Stream<T> limit(long maxSize); 跳过前几个 Stream<T> skip(long n); 组合 static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以
下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
5. 将两个队伍合并为一个队伍;存储到一个新集合中。
6. 根据姓名创建 Person 对象;存储到一个新集合中。
7. 打印整个队伍的Person对象信息。
两个队伍(集合)的代码如下:
import java.util.ArrayList; 而 Person 类的代码为: import java.util.List; public class DemoArrayListNames { public static void main(String[] args) { //第一支队伍 ArrayList<String> one = new ArrayList<>(); one.add("迪丽热巴"); one.add("宋远桥"); one.add("苏星河"); one.add("石破天"); one.add("石中玉"); one.add("老子"); one.add("庄子"); one.add("洪七公"); //第二支队伍 ArrayList<String> two = new ArrayList<>(); two.add("古力娜扎"); two.add("张无忌"); two.add("赵丽颖"); two.add("张三丰"); two.add("尼古拉斯赵四"); two.add("张天爱"); two.add("张二狗"); // .... } }
而 Person 类的代码为:
public class Person { private String name; public Person() {} public Person(String name) { this.name = name; } @Override public String toString() { return "Person{name=‘" + name + "‘}"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
解答:
import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class DemoStreamNames { public static void main(String[] args) { List<String> one = new ArrayList<>(); // ... List<String> two = new ArrayList<>(); // ... // 第一个队伍只要名字为3个字的成员姓名; // 第一个队伍筛选之后只要前3个人; Stream<String> streamOne = one.stream().filter(s ‐> s.length() == 3).limit(3); // 第二个队伍只要姓张的成员姓名; // 第二个队伍筛选之后不要前2个人; Stream<String> streamTwo = two.stream().filter(s ‐> s.startsWith("张")).skip(2); // 将两个队伍合并为一个队伍; // 根据姓名创建Person对象; // 打印整个队伍的Person对象信息。 Stream.concat(streamOne, streamTwo).map(Person::new).forEach(System.out::println); }}
运行效果:
Person{name=‘宋远桥‘} Person{name=‘苏星河‘} Person{name=‘石破天‘} Person{name=‘张天爱‘} Person{name=‘张二狗‘}
在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。那么考虑
一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑?
双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方
法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
原文:https://www.cnblogs.com/qqfff/p/13253868.html