1.stream方法使用
stream跟函数接口关系非常紧密,没有函数接口stream就无法工作。函数接口是指内部只有一个抽象方法的接口。通常函数接口出现的地方都可以使用Lambda表达式,所以不必记忆函数接口的名字。
2.中间操作方法
2.1 concat() : 合并两个stream
签名:
static Stream concat(Stream extends T> a,tream extends T> b)
作用:
- 创建一个延迟连接的流,其元素是a的所有元素和b的所有元素。
- 如果两个输入流都是有序的,则对所得到的流进行排序。
- 如果任一输入流是并行的,则得到的流是平行的。
- 关闭结果流时,将调用两个输入流的关闭处理程序。
代码:
public static void main(String[] args) { // 创建两个stream对象 Stream language1 = Stream.of("PHP", "JAVA"); Stream language2 = Stream.of("GO", "PYTHON"); // 使用中间操作concat,合并两个stream对象 Stream concat = Stream.concat(language1, language2); // 使用结束操作collect,转成list List collect = concat.collect(Collectors.toList()); System.out.println(collect); // 输出: [PHP, JAVA, GO, PYTHON]}
更多concat用例
2.2 distinct() : 去重
说明: 返回:返回由该流的不同元素(根据 Object.equals(Object) )组成的Stream。
代码:
List strings = Arrays.asList("AA", "BB", "CC", "AA", "BB");List collect = strings.stream().distinct().collect(Collectors.toList());System.out.println(collect);//[AA, BB, CC]
2.3 filter() : 过滤
签名:
Stream filter(Predicate super T> predicate)
返回:作用是返回一个只包含满足predicate条件元素的Stream
代码:
List integers = Arrays.asList(10, 12, 71, 63, 921, 68, 121);List collect = integers.stream().filter(integer -> integer > 100).collect(Collectors.toList());System.out.println(collect);//[921, 121]
2.4 flatMap() : 合并
签名:
Stream flatMap(Function super T,? extends Stream extends R>> mapper)
作用:把几个小的list转换到一个大的list
效果示意图:
代码:
// 初始化一个嵌套集合 [[1, 2], [3, 4, 5]]ArrayList> arrayLists = new ArrayList(){{ add(Arrays.asList(1, 2)); add(Arrays.asList(3, 4, 5));}};// 使用flatMap 把多个小集合合并成大集合List collect = arrayLists.stream().flatMap(pList -> pList.stream()).collect(Collectors.toList());System.out.println(collect);// 输出 [1, 2, 3, 4, 5]
2.5 limit() : 截取(返回前N个元素)
签名:
Stream limit(long maxSize)
作用:对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;
代码:
// 声明一个listList integers = Arrays.asList(1, 2, 3, 4, 5);// 取出前三个元素List collect1 = integers.stream().limit(3).collect(Collectors.toList());System.out.println(collect1);// 输出 [1, 2, 3]// 取出前6个元素List collect2 = integers.stream().limit(6).collect(Collectors.toList());System.out.println(collect2);// 输出 [1, 2, 3, 4, 5]
2.6 skip() : 截取(返回不包含前N个元素)
签名:
Stream skip(long n)
作用:返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream;
代码:
// 声明一个listList integers = Arrays.asList(1, 2, 3, 4, 5);// 取出前三个元素List collect1 = integers.stream().skip(3).collect(Collectors.toList());System.out.println(collect1);// 输出 [4, 5]// 取出前6个元素List collect2 = integers.stream().skip(6).collect(Collectors.toList());System.out.println(collect2);// 输出 []
2.7 sorted(): 排序
签名:
Stream sorted()和Stream sorted(Comparator super T> comparator)。
作用:返回排序后的Stream;
代码:对整型集合排序
// 声明一个listList integers = Arrays.asList(11, 42, 23, 74, 5);// 默认自然序排序List collect = integers.stream().sorted().collect(Collectors.toList());System.out.println("自然序排序后结果: " + collect + "");List collect2 = integers.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());System.out.println("逆序排序后结果: " + collect2 + "");
代码:对字符串集合排序
// 声明一个list List strings = Arrays.asList("PHP", "JAVA", "GO", "C", "PYTHON","LUA","ABC"); List collect = strings.stream().sorted().collect(Collectors.toList()); System.out.println("自然序排序后结果 => " + collect + ""); //自然序排序后结果 => [ABC, C, GO, JAVA, LUA, PHP, PYTHON] List collect1 = strings.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()); System.out.println("自然序逆排序后结果 => " + collect1 + ""); //自然序逆排序后结果 => [PYTHON, PHP, LUA, JAVA, GO, C, ABC] List collect2 = strings.stream().sorted((str1,str2)-> str1.length()- str2.length()).collect(Collectors.toList()); System.out.println("根据长度正序排序 => " + collect2 + ""); // 根据长度正序排序 => [C, GO, PHP, LUA, ABC, JAVA, PYTHON] List collect3 = strings.stream().sorted((str1,str2)-> str2.length()- str1.length()).collect(Collectors.toList()); System.out.println("根据长度逆序排序 => " + collect3 + ""); //根据长度逆序排序 => [PYTHON, JAVA, PHP, LUA, ABC, GO, C]
由上面例子,可以看出对字符串集合排序时,会发现简单使用sorted会有问题!!
2.8 map(): 递归处理
签名:
Stream map(Function super T,? extends R> mapper)。
作用:返回一个对当前所有元素执行mapper之后的结果组成的Stream。直观的说,就是对每个元素按照某种操作进行转换,转换前后Stream中元素的个数不会改变,但元素的类型取决于转换之后的类型;
代码
// 声明一个listList strings = Arrays.asList("PHP", "JAVA", "GO", "C", "PYTHON","LUA");List collect = strings.stream().map(s -> s.toLowerCase()).collect(Collectors.toList());System.out.println("转小写 ==> " + collect + "");// 转小写 ==> [php, java, go, c, python, lua]// 声明一个listList integers = Arrays.asList(1, 2, 3, 4, 5);List collect1 = integers.stream().map(integer -> integer * 2).collect(Collectors.toList());System.out.println("元素都乘以2 ==> " + collect1 + "");// 元素都乘以2 ==> [2, 4, 6, 8, 10]
3.结束操作方法
3.1 allMatch(): 判断(都是)
签名:
boolean allMatch(Predicate super T> predicate)
作用:判断条件里的元素都满足,则返回true
代码
// 声明一个listList integers = Arrays.asList(1, 2, 3, 4, 5);boolean a = integers.stream().allMatch(integer -> integer > 10);System.out.println("所有元素都大于10 ==> " + a + "");// 所有元素都大于10 ==> falseboolean b = integers.stream().allMatch(integer -> integer " + b + "");// 所有元素都小于10 ==> true
3.2 anyMatch(): 判断(有一个是)
签名:
boolean anyMatch(Predicate super T> predicate)
作用:判断条件里的元素有一个满足,则返回true
代码
// 声明一个listList integers = Arrays.asList(1, 2, 3, 4, 5, 11);boolean a = integers.stream().anyMatch(integer -> integer > 10);System.out.println("所有元素都大于10 ==> " + a + "");// 所有元素都大于10 ==> trueboolean b = integers.stream().anyMatch(integer -> integer " + b + "");// 所有元素都小于10 ==> true
3.3 noneMatch(): 判断(都不是)
签名:
boolean noneMatch(Predicate super T> predicate)
作用:跟allMatch相反,判断条件里的元素都不满足,则返回true
代码
// 声明一个listList integers = Arrays.asList(1, 2, 3, 4, 5, 11);boolean a = integers.stream().noneMatch(integer -> integer > 10);System.out.println("所有元素都大于10 ==> " + a + "");// 所有元素都大于10 ==> trueboolean b = integers.stream().noneMatch(integer -> integer " + b + "");// 所有元素都小于10 ==> false
3.4 count(): 统计
签名:
long count()
作用:统计个数
代码
// 声明一个listList integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10);long count = integers.stream().count();System.out.println("总个数 ==> " + count + "");// 总个数 ==> 12long count1 = integers.stream().filter(integer -> integer > 5).count();System.out.println("大于5的总个数 ==> " + count1 + "");// 大于5的总个数 ==> 7long count2 = integers.stream().filter(integer -> integer > 5).distinct().count();System.out.println("大于5的去重后的总个数 ==> " + count2 + "");// 大于5的去重后的总个数 ==> 5
3.5 max()、mix(): 最大和最小
签名:
Optional max(Comparator super T> comparator)Optional min(Comparator super T> comparator)
作用:返回最大和最小
代码
// 声明一个整型listList integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Integer max = integers.stream().max(Comparator.comparing(Integer::valueOf)).get();System.out.println(" 最大整数值 ==> " + max + "");Integer min = integers.stream().min(Comparator.comparing(Integer::valueOf)).get();System.out.println(" 最小整数值 ==> " + min + "");// 声明一个字符串listList strings = Arrays.asList("B", "E", "F", "G", "H","Z","A");String maxs = strings.stream().max(Comparator.comparing(String::valueOf)).get();System.out.println(" 最大字符串 ==> " + maxs + "");String mins = strings.stream().min(Comparator.comparing(String::valueOf)).get();System.out.println(" 最小字符串 ==> " + mins + "");/**输出: 最大整数值 ==> 10 最小整数值 ==> 1 最大字符串 ==> Z 最小字符串 ==> A*/
获取最大和最小对象
public class Main { public static void main(String[] args) { List emps = new ArrayList(); emps.add(new Employee("小明", 16)); emps.add(new Employee("张三", 28)); emps.add(new Employee("李四", 32)); // 设置比较器,以年龄大小来比较 Comparator comparator = Comparator.comparing(Employee::getAge); Employee minObject = emps.stream().min(comparator).get(); Employee maxObject = emps.stream().max(comparator).get(); System.out.println("最小对象 = " + minObject); System.out.println("最大对象 = " + maxObject); /** 输出: 最小对象 ==> Name:- 小明 Age:- 16 最大对象 ==> Name:- 李四 Age:- 32 */ } static class Employee { private String name; private int age; public Employee(String name, int age) { setName(name); setAge(age); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { StringBuilder str = null; str = new StringBuilder(); str.append(" Name:- " + getName() + " Age:- " + getAge()); return str.toString(); } }}
3.6 findAny() findFirst() 查找
签名:
Optional findFirst()Optional findAny()
作用:
- findFirst: 返回集合的第一个对象
- findAny: 返回这个集合中,取到的任何一个对象
@注意:
1. 在串行的流中,findAny和findFirst返回的,都是第一个对象
2. 在并行的流中,findAny返回的是最快处理完的那个线程的数据
3. 在并行操作中,对数据没有顺序上的要求,那么findAny的效率会比findFirst要快的
代码
// 声明一个整型listList integers = Arrays.asList(10, 32, 23, 14, 51, 64, 72, 81, 59, 110);Object[] objects = integers.stream().sorted().toArray();Integer findFirst = integers.stream().filter(integer -> integer > 15).sorted().findFirst().get();Integer findAny = integers.stream().filter(integer -> integer > 15).sorted().findAny().get();System.out.println("排序后 => " + Arrays.toString(objects) + "");System.out.println("findFirst => " + findFirst + "");System.out.println("findAny => " + findAny + "");/**输出: 排序后 => [10, 14, 23, 32, 51, 59, 64, 72, 81, 110] findFirst => 23 findAny => 23*/
3.7 reduce() 生成一个符合的值
签名:
三种重写形式:
// 第一种Optional reduce(BinaryOperator accumulator)// 第二种T reduce(T identity, BinaryOperator accumulator)// 第三种 U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)
说明:
reduce操作可以实现从一组元素中生成一个值,sum()、max()、min()、count()等都是reduce操作,将他们单独设为函数只是因为常用
代码
// 声明一个整型listList integers = Arrays.asList(1,2,3,4,5);// 集合元素求和,Integer sum = integers.stream().reduce(Integer::sum).get();System.out.println("求和 => " + sum + "");// 集合元素求和后,加上初始值 100Integer sum1 = integers.stream().reduce(100, (total, item) -> total + item);System.out.println("求和后再加100-A => " + sum1 + "");Integer sum2 = integers.stream().reduce(100,Integer::sum);System.out.println("求和后再加100-B => " + sum2 + "");// 最小值Integer min = integers.stream().reduce(Integer::min).get();System.out.println("最小值 => " + min + "");// 最大值Integer max = integers.stream().reduce(Integer::max).get();System.out.println("最大值 => " + max + "");// 集合中的元素乘积Integer product = integers.stream().reduce((a, b) -> a * b).get();System.out.println("相乘结果: => " + product + "");// 找出最长的单词Stream stream = Stream.of("go", "php", "Java");String lengthStr = stream.reduce((s1, s2) -> s1.length() >= s2.length() ? s1 : s2).get();System.out.println("最长的单词: => " + lengthStr + "");/**输出: 求和 => 15 求和后再加100-A => 115 求和后再加100-B => 115 最小值 => 1 最大值 => 5 相乘结果: => 120 最长的单词: => Java*/
3.8 forEach() 遍历
签名:
void forEach(Consumer super E> action)
**作用:**是对容器中的每个元素执行action指定的动作,也就是对元素进行遍历
代码
// 声明一个MapHashMap gradeMap = new HashMap(4) {{ put("张三", 82); put("李四", 70); put("小明", 91); put("老王", 59);}};// 遍历mapgradeMap.entrySet().stream().forEach(item-> { System.out.println("name = " + item.getKey() + ", fraction = [ " + item.getValue() + " ]");});// 遍历集合List strings = Arrays.asList("张三", "李四", "小明", "老王");strings.stream().forEach(s -> System.out.println("name = [ " + s + " ]"));
3.9 forEachOrdered() 遍历
签名:
void forEachOrdered(Consumer super T> action)
**作用:**是对容器中的每个元素执行action指定的动作,也就是对元素进行遍历
@注意:
1. 在串行的流中,forEach和forEachOrdered遍历输出的结果一样。
2. 在并行的流中,forEach每次输出的结果不一致。
3. 在并行的流中,forEachOrdered每次输出的结果一致。
代码
// 在串行流中: 遍历集合List strings = Arrays.asList(1, 2, 3, 4, 5);strings.stream().forEach(s -> System.out.println("串行流-forEach => " + s + " "));strings.stream().forEachOrdered(s -> System.out.println("串行流-forEachOrdered => " + s + " "));// 在并行流中: 遍历集合strings.parallelStream().forEach(s -> System.out.println("并行流-forEach => " + s + " "));strings.parallelStream().forEachOrdered(s -> System.out.println("并行流-forEachOrdered => " + s + " "));/**第一次遍历输出: 串行流-forEach => 1 串行流-forEach => 2 串行流-forEach => 3 串行流-forEach => 4 串行流-forEach => 5 串行流-forEachOrdered => 1 串行流-forEachOrdered => 2 串行流-forEachOrdered => 3 串行流-forEachOrdered => 4 串行流-forEachOrdered => 5 并行流-forEach => 3 并行流-forEach => 5 并行流-forEach => 4 并行流-forEach => 2 并行流-forEach => 1 并行流-forEachOrdered => 1 并行流-forEachOrdered => 2 并行流-forEachOrdered => 3 并行流-forEachOrdered => 4 并行流-forEachOrdered => 5 第二次遍历输出: 串行流-forEach => 1 串行流-forEach => 2 串行流-forEach => 3 串行流-forEach => 4 串行流-forEach => 5 串行流-forEachOrdered => 1 串行流-forEachOrdered => 2 串行流-forEachOrdered => 3 串行流-forEachOrdered => 4 串行流-forEachOrdered => 5 并行流-forEach => 2 并行流-forEach => 1 并行流-forEach => 3 并行流-forEach => 4 并行流-forEach => 5 并行流-forEachOrdered => 1 并行流-forEachOrdered => 2 并行流-forEachOrdered => 3 并行流-forEachOrdered => 4 并行流-forEachOrdered => 5 */
Java8 parallelStream浅析-知乎
3.10 toArray() 转成数组
签名:
A[] toArray(IntFunction generator)
作用: 将流转成数组
代码
List integerList = Arrays.asList(1, 2, 3,4,5,6,7,8,9);Integer[] integers = integerList.stream().filter(integer -> integer % 3 == 0).toArray(Integer[]::new);System.out.println("整型集合过滤后的结果,toArray -> " + Arrays.toString(integers) + "");// 整型集合过滤后的结果,toArray -> [3, 6, 9]List stringsList = Arrays.asList("PHP", "GO", "JAVA", "PYTHON", "LUA");String[] strings = stringsList.stream().filter(s -> s.length() > 3).toArray(String[]::new);System.out.println("字符串集合过滤后的结果,toArray -> " + Arrays.toString(strings) + "");// 字符串集合过滤后的结果,toArray -> [JAVA, PYTHON]
3.11 collect()
由于collect过于特殊和强大,拉出去单讲【collect() 和 Collectors(收集器) 】。