Java—— Stream流
作用
结合了Lambda表达式,简化集合、数组的操作
Stream流的使用步骤
先得到一条Stream流(流水线),并把数据放上去
数据的类型 | 方法名 | 说明 |
单列集合 | 单列集合名.stream () | Collection中 的默认方法 |
双列集合 | 双列集合名.keySet().stream () | 先进行预处理再 转化为Stream流 |
双列集合名.entrySet().stream () | ||
数组 | Arrays.stream (T[] array) | Arrays工具类中 的静态方法 |
一堆零散数据 | Stream.of (T... values) | Stream接口中 的静态方法 |
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.stream.Stream;public class Test1 {public static void main(String[] args) {//单列集合获取Stream流ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "aa", "bb", "cc", "dd");list.stream().forEach(s -> System.out.println(s));//aa//bb//cc//dd//双列集合获取Stream流HashMap<String, String> hm = new HashMap<>();hm.put("苹果", "apple");hm.put("香蕉", "banana");hm.put("橘子", "orange");//方式1:只获取键hm.keySet().stream().forEach(s -> System.out.println(s));//苹果//香蕉//橘子//方式2:获取键值对对象hm.entrySet().stream().forEach(s -> System.out.println(s));//苹果=apple//香蕉=banana//橘子=orangehm.entrySet().stream().forEach(s -> System.out.println(s.getValue()));//apple//banana//orangehm.entrySet().stream().forEach(s -> System.out.println(s.getKey()));//苹果//香蕉//橘子//数组获取Stream流String[] arr = {"cat", "dog", "pig"};Arrays.stream(arr).forEach(s -> System.out.println(s));//cat//dog//pig//同种类型的一堆数据Stream.of(1, 2, 3).forEach(s -> System.out.println(s));//1//2//3}
}
使用中间方法对流水线上的数据进行操作
注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
注意2: 修改Stream流中的数据,不会影响原来集合或者数组中的数据
名称 | 说明 |
Stream<T> filter (过滤条件) | 过滤 |
Stream<T> limit (long maxSize) | 获取前几个元素 |
Stream<T> skip (long n) | 跳过前几个元素 |
Stream<T> distinct() | 元素去重,依赖 (hashCode和equals方法) |
Stream.concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
Stream<R> map(Function<T,R> mapper) | 转换流中的数据类型 |
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;public class Test2 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三-23", "李四-24", "王五-25");//过滤,留下姓张的//匿名内部类list.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {//参数s代表流中的每一个元素//返回值为true代表该元素留下//返回值为false代表该元素被过滤return s.startsWith("张");}}).forEach(s -> System.out.println(s));//张三-23//简化为lambda表达式list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));//张三-23//获取前几个元素list.stream().limit(2).forEach(s -> System.out.println(s));//张三-23//李四-24//跳过前几个元素list.stream().skip(2).forEach(s -> System.out.println(s));//王五-25System.out.println("-----------------");//元素去重ArrayList<String> list1 = new ArrayList<>();Collections.addAll(list1, "苹果", "苹果", "香蕉", "橘子");list1.stream().distinct().forEach(s -> System.out.println(s));//苹果//香蕉//橘子//合并a和b两个流为一个流Stream.concat(list.stream(), list1.stream()).forEach(s -> System.out.println(s));//张三-23//李四-24//王五-25//苹果//苹果//香蕉//橘子//转换流中的数据类型,将list中字符串中的年龄以int类型输出//匿名内部类//第一个泛型表示元素原来的类型//第二个泛型表示元素转化后的类型//参数s代表流中每一个元素list.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.parseInt(s.split("-")[1]);}}).forEach(s -> System.out.println(s));//23//24//25//简化为lambda表达式list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));//23//24//25}
}
使用终结方法对流水线上的数据进行操作
名称 | 说明 |
void forEach(Consumer action) | 遍历 |
long count() | 统计 |
toArray() | 收集流中的数据,放到数组中 |
collect(Collector collector) | 收集流中的数据,放到集合中 |
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Consumer;
import java.util.function.IntFunction;public class Test3 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "苹果", "橘子", "香蕉");//遍历//匿名内部类list.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String s) {//形参s代表流中每一个元素System.out.println(s);}});//lambda表达式list.stream().forEach(s -> System.out.println(s));//苹果//橘子//香蕉//统计long count = list.stream().count();System.out.println(count);//3//收集流中的数据,放到数组中//toArray方法的参数的作用:负责创建一个指定类型的数组//toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组当中//toArray方法的返回值:是一个装着流里面所有数据的数组//空参默认生成的是Object类型的数组Object[] arr1 = list.stream().toArray();System.out.println(Arrays.toString(arr1));//[苹果, 橘子, 香蕉]//生成指定类型的数组://匿名内部类//IntFunction的泛型:具体类型的数组//apply的形参:流中数据的个数,要跟数组的长度保持一致//apply的返回值:具体类型的数组//方法体:就是创建数组String[] arr2 = list.stream().toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[value];}});//lambda表达式String[] arr3 = list.stream().toArray(value -> new String[value]);System.out.println(Arrays.toString(arr3));//[苹果, 橘子, 香蕉]}
}
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;public class Test4 {public static void main(String[] args) {//collect(Collector collector) 收集流中的数据,放到集合中ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三-23", "张弓长-23", "李四-24", "王五-25");//收集流中的数据,放到集合中,要求收集后的数据都姓张//list集合List<String> newList = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toList());System.out.println(newList);//[张三-23, 张弓长-23]//Set集合,可以去重Set<String> newSet = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toSet());System.out.println(newSet);//[张三-23, 张弓长-23]//Map集合//确定键是姓名,值是年龄//匿名内部类//Collectors.toMap方法有两个参数//第一个是键的规则//第二个是值的规则//Function有两个泛型//第一个泛型是元素原来的类型//第二个泛型是元素转换后的类型//apply方法中//s表示每一个流中的数据//返回值就代表集合中的键和值Map<String, Integer> newMap = list.stream().collect(Collectors.toMap(new Function<String, String>() {@Overridepublic String apply(String s) {return s.split("-")[0];}},new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.parseInt(s.split("-")[1]);}}));System.out.println(newMap);//{李四=24, 张三=23, 王五=25, 张弓长=23}//lambda表达式list.stream().collect(Collectors.toMap(s -> s.split("-")[0],s -> Integer.parseInt(s.split("-")[1])));System.out.println(newMap);//{李四=24, 张三=23, 王五=25, 张弓长=23}}
}