j2ee做网站,济南做网站互联网公司排名,云速建站可以建个人网站吗,云南建设厅网站工程师所属专栏#xff1a;Java学习 Stream流是JDK 8引入的一个概念#xff0c;它提供了一种高效且表达力强的方式来处理数据集合#xff08;如List、Set等#xff09;或数组。Stream API可以以声明性方式#xff08;指定做什么#xff09;来处理数据序列。流操作可以被分为两大… 所属专栏Java学习 Stream流是JDK 8引入的一个概念它提供了一种高效且表达力强的方式来处理数据集合如List、Set等或数组。Stream API可以以声明性方式指定做什么来处理数据序列。流操作可以被分为两大类中间操作Intermediate Operations和终端操作Terminal Operations。 1. Stream流的适用对象
先得到一条Stream流并把数据放上去,再进行中间操作和终端操作
获取方式方法名说明单列集合default StreamEstream()Collection中的默认方法双列集合无无法直接使用Stream流数组public static T StreamT stream(T[] array)Arrays工具类中的静态方法一堆零散数据public static T StreamT of(T...values)Stream接口中的静态方法 先来看单列集合的例子
public class Demo1 {public static void main(String[] args) {ArrayListString arrayList new ArrayList();Collections.addAll(arrayList, a, b, c, d, e);// 获取Stream流把集合中的数据放到流上StreamString stream1 arrayList.stream();//内部类方式打印stream1.forEach(new ConsumerString() {Overridepublic void accept(String s) {System.out.print(s);}});System.out.println();//获取流之后直接通过lambda表达式进行打印arrayList.stream().forEach(s - System.out.print(s));}
}
对于双列集合需要通过keySet() 或 entrySet() 转化为单列集合再获取Stream
public class Demo2 {public static void main(String[] args) {HashMapString,Integer hashMap new HashMap();hashMap.put(aaa,1);hashMap.put(bbb,2);hashMap.put(ccc,3);hashMap.put(ddd,4);//双列集合第一种获取Stream流hashMap.keySet().stream().forEach(s - System.out.print(s ));System.out.println();//双列集合第二种获取hashMap.entrySet().stream().forEach(s - System.out.print(s ));}
} 数组获取Stream流
public class Demo3 {public static void main(String[] args) {int[] arr1 {1, 2, 3, 4, 5};String[] arr2 {a, b, c, d};//获取Stream流Arrays.stream(arr1).forEach(s- System.out.print(s ));System.out.println();//数组中是引用型数据类型也可以获取Stream流Arrays.stream(arr2).forEach(s - System.out.print(s ));}
} 对于不存储在数组或集合中的零散数据可以直接通过Stream接口中的静态方法获取
public class Demo4 {public static void main(String[] args) {Stream.of(1,2,3,4,5).forEach(s- System.out.print(s ));System.out.println();Stream.of(a,b,c).forEach(s- System.out.print(s ));}
}
2. 中间方法 中间操作中间操作可以返回流本身因此可以链式调用多个中间操作中间操作可以是对流的过滤如filter、映射如map、排序如sorted等
在上面的中间方法时只会修改Stream流中的数据不会影响原来集合或数组中的数据并且原来的流只能使用一次
2.1 filter() filter 的参数 Predicate 是一个函数式接口 所以可以先使用匿名内部类的方式再用 lambda 表达式
public class Demo5 {public static void main(String[] args) {ArrayListString arrayList new ArrayList();Collections.addAll(arrayList, aaa, abc, acb, aa, bb, cc);//fitlter 过滤 把a开头的留下其余数据不要arrayList.stream().filter(new PredicateString() {Overridepublic boolean test(String s) {//返回值为true当前数据留下返回值为false当前数据舍弃return s.startsWith(a);}}).forEach(s - System.out.print(s ));System.out.println();// lambda表达式的形式arrayList.stream().filter(s - s.startsWith(a)).forEach(s - System.out.print(s ));System.out.println();//把stream流暂时接收的方式StreamString stream1 arrayList.stream().filter(s - s.startsWith(a));stream1.forEach(s - System.out.print(s ));}
}
由于Stream流只能用一次如果之前的流已经被使用过再次使用就会报错 所以说由于只能使用一次再用一个变量取接收也没有什么意义直接使用链式编程就可以了 并且使用流之后原来集合中的元素也不会改变 2.2 limit() 和 skip()
/* limit() 获取前面几个元素skip() 跳过几个元素*/arrayList.stream().limit(3).forEach(s - System.out.print(s ));System.out.println();arrayList.stream().skip(3).forEach(s - System.out.print(s )); 2.3 distinct()和concat()
distinct()去重是依赖hashCode()和equals()方法的所以如果是自定义类型要手动的重写这两个方法
public class Demo6 {public static void main(String[] args) {ArrayListString arrayList1 new ArrayList();Collections.addAll(arrayList1, aaa, aaa, acb, aa, bb, cc);ArrayListString arrayList2 new ArrayList();Collections.addAll(arrayList2,dd,ee);//去重arrayList1.stream().distinct().forEach(s - System.out.print(s ));System.out.println();//流的合并Stream.concat(arrayList1.stream(),arrayList2.stream()).forEach(s - System.out.print(s ));}
} 2.4 map()
需求获取集合中的数字部分
首先调用split方法进行分割得到数字部分之后再转换为整型
public class Demo7 {public static void main(String[] args) {ArrayListString arrayList new ArrayList();Collections.addAll(arrayList, aaa-11, acb-22, aa-33, bb-44, cc-55);// 获取集合中的数字部分arrayList.stream().map(new FunctionString, Integer() {Overridepublic Integer apply(String s) {//使用split进行分割String[] arr s.split(-);//获取数字部分String num arr[1];//转换为int类型int ans Integer.parseInt(num);return ans;}}).forEach(s - System.out.print(s ));System.out.println();//lambda表达式arrayList.stream().map(s - Integer.parseInt(s.split(-)[1])).forEach(s - System.out.print(s ));}
} 3. 终结方法
名称说明void forEach(Consumer action)遍历long count()统计toArray()收集流中的数据放到数组中collect(Collector collector)收集流中的数据放到集合中
3.1 forEach()和count()
forEach方法在之前已经演示过了就是进行遍历的 forEach中的参数Consumer也是一个函数式接口也可以先使用匿名内部类的方式再用 lambda 表达式
public class Demo8 {public static void main(String[] args) {ArrayListString arrayList new ArrayList();Collections.addAll(arrayList, aaa, aaa, acb, aa, bb, cc);arrayList.forEach(new ConsumerString() {Overridepublic void accept(String s) {System.out.print(s );}});System.out.println();arrayList.forEach(s- System.out.print(s ));System.out.println();//统计个数long l arrayList.stream().count();System.out.println(l);}
}
count() 的返回值为long类型的可以定义一个变量进行接收
3.2 toArray()
toArray()是收集流里面的数据放在数组中 toArray()方法有两种返回类型一种是Object类型的另一种是指定类型的Object类型的比较简单直接用Object类型的变量来接收就可以了
public class Demo9 {public static void main(String[] args) {ArrayListString arrayList new ArrayList();Collections.addAll(arrayList, aaa, aaa, acb, aa, bb, cc);Object[] array1 arrayList.stream().toArray();System.out.println(Arrays.toString(array1));}
}
接下来看指定类型 toArray方法的参数也是一个函数式接口还是使用匿名内部类和lambda表达式两种方式演示
public class Demo9 {public static void main(String[] args) {ArrayListString arrayList new ArrayList();Collections.addAll(arrayList, aaa, aaa, acb, aa, bb, cc);//IntFunction的泛型具体类型的数组//apply方法的形参流中数据的个数返回的数组的长度要一致//返回值就是具体类型的数组String[] array2 arrayList.stream().toArray(new IntFunctionString[]() {Overridepublic String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(array2));//lambda表达式String[] array arrayList.stream().toArray(value - new String[value]);System.out.println(Arrays.toString(array));}
}
IntFunction的泛型是具体类型的数组 apply方法的形参表示流中数据的个数返回的数组的长度要一致最后的返回值就是具体类型的数组 3.3 collect()
collect() 方法就是收集流里面的数据放到集合中下面先来演示收集到List和Set集合中的例子
public class Demo10 {public static void main(String[] args) {ArrayListString arrayList new ArrayList();Collections.addAll(arrayList, 张三-男-23, 李四-男-21, 王五-女-22, 钱七-女-22);// 把所有男性收集起来//收集到List集合中ListString list arrayList.stream().filter(s - 男.equals(s.split(-)[1])).collect(Collectors.toList());//收集到Set集合中SetString set arrayList.stream().filter(s - 男.equals(s.split(-)[1])).collect(Collectors.toSet());}
}
收集到List和Set集合中的数据的区别还是和List和Set集合的区别一样的Set集合中不能有重复的元素如果流中收集的数据存在重复的数据在收集到Set集合之后就会进行去重
接下来看Map集合由于Map集合是一个双列集合所以需要指定键和值的生成规则 这里的生成规则比较复杂
//收集到Map集合中/*** toMap : 参数一表示键的生成规则* 参数二表示值的生成规则* 参数一* Function 泛型一表示流中的数据类型* 泛型二表示Map集合中键的类型* 方法 apply 形参表示流中的每一个数据* 方法体生成键的代码* 返回值已经生成的键**/MapString, Integer map1 arrayList.stream().filter(s - 男.equals(s.split(-)[1])).collect(Collectors.toMap(new FunctionString, String() {Overridepublic String apply(String s) {return s.split(-)[0];}}, new FunctionString, Integer() {Overridepublic Integer apply(String s) {return Integer.parseInt(s.split(-)[2]);}}));System.out.println(map1);
//lambda表达式MapString, Integer map2 arrayList.stream().filter(s - 男.equals(s.split(-)[1])).collect(Collectors.toMap(s - s.split(-)[0], s - Integer.parseInt(s.split(-)[2])));System.out.println(map2); 由于Map集合中是不能有重复的键的所以如果Stream流获取的键中存在了重的元素就会报错
4. Stream流的作用和使用步骤总结
作用Stream流就是结合了lambda表达式简化集合和数组的操作 使用步骤 1. 获取Stream流对象 2.使用中间方法处理数据 3.使用终结方法处理数据