流式计算
- 能用流解决的用迭代必然能解决.
- 流可以进行并行计算,大大提高效率.
- 流处理==集合==
- 一个 流只能使用 ==一次==
- ==并行流需要的条件比较多==
流与集合的区别
- 流不存储数据
- 流的操作不会影响其数据源
- 流的操作是==惰性的==,即 有需求 才会进行计算,可以操作==无限流==
流的创建
利用 collection 集合类的 stream 方法
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.println(arrayList.parallelStream().filter(o -> o % 2 > 0).count());
}
利用静态的 stream.of 方法
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
Stream<ArrayList<Integer>> stream = Stream.of(arrayList);
System.out.println(stream.count());
}
- stream.of 方法是可变参数
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
使用 empty 创建空流
public static void main(String[] args) {
Stream<Object> empty = Stream.empty();
System.out.println(empty.count());
}
使用 generate 创建无限流
public static void main(String[] args) {
Stream<Integer> generate = Stream.generate(() -> Integer.MAX_VALUE);
System.out.println(generate.count()); // 永远不会执行
}
使用迭代器创建
public static void main(String[] args) {
Stream<BigInteger> iterate = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
System.out.println(iterate.count());
}
流的操作
- 流的操作会生成一个新的流,不会对原有的流有任何侵入.
filter 方法
- 匹配
- 筛选
- 过滤
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println(stream.filter(n -> n % 2 == 0).count());
}
map 方法
- 转换
- 映射
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
stream.map(n -> n+1).forEach(System.out::println);
distinct 方法
- 元素去重
public static void main(String[] args) {
Stream<Integer> concat = Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6, 6));
concat.distinct().forEach(System.out::println);
}
sorted
- 排序
peek
- 产生另一个流,元素与原来的流中的元素相同,在访问某个元素时,就回调用action
- 类似一个监视器
public static void main(String[] args) {
Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6, 6))
.peek(o-> System.out.print("hello"))
.forEach(System.out::print);
}
输出 : hello1hello2hello3hello4hello5hello6hello6
遍历
- 并行流的遍历顺序是不确定的
Stream<Integer> concat = Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6));
concat.parallel().forEach(System.out::println);
- 使用 ==forEachOrdered== 避免随机顺序的问题,但是牺牲了部分性能
Stream<Integer> concat = Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6));
concat.parallel().forEachOrdered(System.out::println);
将流转回 array
- 使用 toArray
public static void main(String[] args) {
Stream<Integer> concat = Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6));
Integer[] integers = concat.toArray(Integer[]::new);
System.out.println(Arrays.toString(integers));
}
- 使用 collect 方法
public static void main(String[] args) {
Stream<Integer> concat = Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6));
List<Integer> integers = concat.collect(Collectors.toList());
System.out.println(integers);
}
抽取子流和链接流
抽取子流
- 从前截取
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
stream.limit(3).forEach(System.out::println);
}
- 从后截断
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
stream.skip(3).forEach(System.out::println);
}
链接流
public static void main(String[] args) {
Stream<Integer> concat = Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6));
concat.forEach(System.out::println);
}
流转换为 map
- 使用 toMap 可解决,在键可能会冲突时,使用
(existVal, newVal) -> existVal)来选择需要保留的键值对,否则会抛出异常.
class Student {
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
public static void main(String[] args) {
Student a = new Student(1, "a");
Student d = new Student(1, "d");
Student b = new Student(2, "b");
Student c = new Student(3, "c");
List<Student> students = Arrays.asList(a, b, c, d);
Map<Integer, String> collect = students.parallelStream().collect(Collectors.toMap(
student -> student.id, student -> student.name, (existVal, newVal) -> existVal));
String s = collect.get(1);
System.out.println(s);
}
- 转化为 ==键--集合== 对
Map<Integer, List<Student>> collect = students.parallelStream().collect(Collectors.groupingBy(Student::getId));
基本类型流
IntStream
- 可以存储
short char byteboolean int
doubleStream
- 可以存储
double float
LongStream
- 存储
long