java 发展史
java8-stream-流操作
java 8 全新引入的Stream API 核心接口就是:
java.util.stream.Stream< T > 接口
好处:
代码简洁
代码语义清晰
代码示例:
公共部分代码
package com.test.testjavaee;
import lombok.Data;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @date 2018/7/24 16:45
* @since
*/
public class Java8_stream {
public static void main(String[] args) {
List<Temp> temps = new ArrayList<>();
temps.add(new Temp("张三", 18, 800, "2017/06/15 14:11:17"));
temps.add(new Temp("李四", 19, 1500, "2017/06/14 14:11:17"));
temps.add(new Temp("王五", 25, 2000, "2017/06/16 13:11:17"));
temps.add(new Temp("王五1", 19, 900, "2017/06/16 14:10:17"));
temps.add(new Temp("王五2", 21, 1800, "2017/06/17 14:11:17"));
//**1,创建 stream 的几种方式
testCreateStream();
//**2,filter,中间操作,对list 集合进行条件判断,留下满足条件的数据。
testFilter();
//**3,map,中间操作
testMap();
//4,flatMap 合并两个流
testFlatMap();
//5,distinct,中间操作,去重
testDistinact(temps);
//6,peek,中间操作
testPeek(temps);
//7,spike,limit,中间操作
testSpikeAndLimit();
// ========================以下为终端操作=========================================
//**8,接口终端操作,forEach,forEachOrdered
testForEach(temps);
//9,终端操作 toArray,把集合转换成数组
testToArray(temps);
//10,终端操作,min,max
testMinAndMax(temps);
//11,终端操作,findFirst,findAny
testFindFirstAndFindAny(temps);
//12,终端操作,count,anyMatch,allMatch,noneMatch
test_count_anyMatch_allMatch_noneMatch();
//13,终端操作,reduce,可以用来累计求和等操作
testReduce();
//**14,终端操作,collect,归约操作的方式collect,收集器操作,收集器操作,可以当做是一种更高级的归约操作;
testCollect(temps);
//在java8中,很多的stream的终端操作,都返回了一个Optional<T>对象,这个对象,是用来解决空指针的问题,而产生的一个类
}
}
@Data
class Temp{
String name;
int age;
double salary;
String brithday;
public Temp(){}
public Temp(String name){
this.name = name;
}
public Temp(String name, int age, double salary){
this.name = name;
this.age = age;
this.salary = salary;
}
public Temp(String name, int age, double salary, String brithday){
this.name = name;
this.age = age;
this.salary = salary;
this.brithday = brithday;
}
}
1,创建 stream 的几种方式:
private static void testCreateStream(){
System.out.println("执行创建stream 方法=====================");
String[] aa = {"a", "b", "c"};
//方式一
Arrays.stream(aa).forEach(System.out::print);
System.out.println();
//方式二
Stream.of(aa).forEach(System.out::print);
System.out.println();
//方式三,最常用的一种方式
Arrays.asList(aa).stream().forEach(System.out::print);
System.out.println();
//方式四
Stream.iterate(0, x -> x + 1).limit(10).forEach(temp -> System.out.print(temp));
System.out.println();
}
2,filter,中间操作,对list 集合进行条件判断,留下满足条件的数据:
private static void testFilter() {
//.filter(当前对象 -> )
Arrays.stream(new String[]{"a","b","c"}).filter(temp -> "c".equals(temp)).forEach(System.out::print);
System.out.println();
}
3,map,中间操作,把当前对象转换成其他类型:
private static void testMap() {
/*作用:
可以用来对对象也可以是基本数据类型也可以是引用类型,进行处理后返回
可以用来对对象中的某个元素进行操作并返回,如只返回该对象中的某个字段
可以对当前对象进行转换,如把 json 转成对象。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
这个接口,接收一个泛型T,返回泛型R,map函数的定义,返回的流,表示的泛型是R对象,这个表示,调用这个函数后,可以改变返回的类型,
*/
Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 3});
stream.map(str -> Integer.toString(str)).forEach(i -> {
System.out.print(i + " ");
});
List<Temp> temps = Arrays.asList(new Temp("a", 21, 800), new Temp("b", 25, 1800), new Temp("c", 19, 2000));
//方式一 .map(当前对象 -> 对当前对象进行操作并返回操作的结果)
temps.stream().map(temp -> temp.getName()).forEach(name -> System.out.print(name));
System.out.println();
//方式二
temps.stream().map(Temp::getName).forEach(name -> System.out.print(name));
System.out.println();
temps.stream().map(temp -> temp.getName().toUpperCase()).collect(Collectors.toList()).forEach(System.out::print);
System.out.println();
temps.stream().map(Temp::getName).map(temp -> (temp + "_").toUpperCase()).collect(Collectors.toList()).forEach(System.out::print);
System.out.println();
temps.stream().filter(temp -> temp.getAge() > 20).map(temp -> temp.getAge() * 2).collect(Collectors.toList()).forEach(temp-> System.out.print(temp + " "));
}
4,flatMap 合并两个流:
private static void testFlatMap() {
String[] strings = {"aaa", "bbb", "ccc"};
String[] strings2 = {"d", "e", "f"};
Arrays.stream(strings).map(str -> str.split("")).flatMap(Arrays::stream).forEach(str-> System.out.print(str));
}
5,distinct、sorted 中间操作,去重、排序:
private static void testDistinact(List<Temp> temps) {
//去重,排序
//默认为升序,
//根据某个字段升序排序, .sorted(Comparator.comparing(Temp::getAge))
Arrays.asList(1, 4, 1, 2, 3).stream().distinct().sorted().forEach(i -> System.out.print(i));
System.out.println();
//设置为降序
Arrays.asList("1", "4", "1", "2", "3").stream().distinct().sorted(Comparator.reverseOrder()).forEach(str -> System.out.print(str));
System.out.println();
//根据某个字段降序排序, .sorted(Comparator.comparing(Temp::getBrithday).reverseOrder())
List<Temp> collect = temps.stream().sorted(Comparator.comparing(Temp::getBrithday).reversed()).collect(Collectors.toList());
collect.forEach(temp -> System.out.println(temp.toString()));
}
6,peek,中间操作,:
private static void testPeek(List<Temp> temps) {
//方式一
Stream<Temp> peek = temps.stream().filter(temp ->
temp.getAge() > 20
).peek(temp -> {
temp.setSalary(temp.getSalary() * 2);
});
//方式二
// Stream<Temp> peek = temps.stream().filter(temp -> {
// return temp.getAge() > 20;
// }).peek(temp -> {
// temp.setSalary(temp.getSalary() * 2);
// });
peek.forEach(temp -> System.out.println(temp.getSalary()));
}
7,spike,limit,中间操作,跳过、限制数量:
private static void testSpikeAndLimit() {
//无限流,从 1 开始。
Stream.iterate(1, x -> ++x).skip(5).limit(10).forEach(temp-> System.out.print(temp + " "));
}
============================ 以下为终端操作 ==================================
8,接口终端操作,forEach,forEachOrdered:
private static void testForEach(List<Temp> temps) {
List<Integer> list = temps.stream().map(Temp::getAge).collect(Collectors.toList());
//串行执行
list.stream().forEach(age -> System.out.print(age + " ") );
System.out.println();
list.stream().forEachOrdered(age-> System.out.print(age + " "));
System.out.println();
//parallelStream 并行执行,forEach 输出的顺序会乱,forEachOrdered 不会乱
list.parallelStream().forEach(age-> System.out.print(age + " "));
System.out.println();
list.parallelStream().forEachOrdered(age-> System.out.print(age + " "));
}
9,终端操作 toArray,把集合转换成数组:
private static void testToArray(List<Temp> temps) {
List<Integer> list = temps.stream().map(temp -> temp.getAge()).collect(Collectors.toList());
//使用 stream 把集合转换成数组
//方式一,指明类型
Integer[] integers = list.stream().toArray(Integer[]::new);
System.out.print(integers.toString() + " ");
//方式二
Integer[] integers1 = list.stream().toArray(temp -> new Integer[list.size()]);
//方式三,未指明类型
Object[] objects = list.stream().toArray();
//使用 list 自带的 toArray 方法进行转换
Integer[] integers2 = list.toArray(new Integer[list.size()]);
Object[] objects1 = list.toArray();
}
10,终端操作,min,max:
private static void testMinAndMax(List<Temp> temps) {
List<Double> list = temps.stream().map(Temp::getSalary).collect(Collectors.toList());
//方式一,Function.identity()
Optional<Double> min = list.stream().min(Comparator.comparing(Function.identity()));
Double d = min.get();
System.out.println("min 方式一 --->" + d);
//方式二
Double d2 = list.stream().min((o1, o2) -> o1.compareTo(o2)).get();
System.out.println("min 方式二 --->" + d2 + "\n");
Double d3 = list.stream().max(Comparator.comparing(Function.identity())).get();
System.out.println("max 方式一 --->" + d3);
Double d4 = list.stream().max((o1, o2) -> o1.compareTo(o2)).get();
System.out.println("max 方式二 --->" + d4 + "\n");
System.out.println(String.format("min:%s;max:%s", d, d3));
}
11,终端操作,findFirst,findAny:
private static void testFindFirstAndFindAny(List<Temp> temps) {
/*findFirst和findAny,通过名字,就可以看到,
对这个集合的流,做一系列的中间操作后,
可以调用findFirst,返回集合的第一个对象,
findAny返回这个集合中,取到的任何一个对象;
*/
List<String> list = temps.stream().map(Temp::getName).collect(Collectors.toList());
//未进行中间操作
Optional<String> first = list.stream().findFirst();
String s = first.get();
Optional<String> any = list.stream().findAny();
String s1 = any.get();
Optional<String> first1 = list.parallelStream().findFirst();
String s2 = first1.get();
String s3 = list.parallelStream().findAny().get();
System.out.println(s + " ====> " + s2);
System.out.println(s1 + " =====> " + s3);
System.out.println("======================================");
//进行中间操作
String s4 = list.stream().filter(temp -> !"李四".equals(temp)).findFirst().get();
String s5 = list.stream().filter(temp -> !"李四".equals(temp)).findAny().get();
String s6 = list.parallelStream().filter(temp -> !"李四".equals(temp)).findFirst().get();
String s7 = list.parallelStream().filter(temp -> !"李四".equals(temp)).findAny().get();
System.out.println(s4 + " -----> " + s6);
System.out.println(s5 + " -----> " + s7);
}
12,终端操作,count,anyMatch,allMatch,noneMatch:
private static void test_count_anyMatch_allMatch_noneMatch() {
List<String> list = Arrays.asList("a", "a", "a", "a", "b", "c", "a");
//anyMatch表示,判断的条件里,任意一个元素成功,返回true
boolean b = list.stream().anyMatch(temp -> "a".equals(temp));
//allMatch表示,判断条件里的元素,所有的都是,返回true
boolean b1 = list.stream().allMatch(temp -> "a".equals(temp));
//noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
boolean b2 = list.stream().noneMatch(temp -> "a".equals(temp));
//返回集合的记录数
long count = list.stream().count();
long count1 = list.stream().filter(temp -> "a".equals(temp)).count();
System.out.println(b);
System.out.println(b1);
System.out.println(b2);
System.out.println(count);
System.out.println(count1);
}
13,终端操作,reduce,可以用来累计求和等操作:
private static void testReduce() {
//reduce 是一种归约操作,将流归约成一个值的操作叫做归约操作,用函数式编程语言的术语来说,这种称为折叠(fold);
List<Integer> list = Stream.iterate(1, x -> ++x).limit(10).collect(Collectors.toList());
//jdk1.7 的做法
Integer i = 0;
for (Integer integer : list){
i += integer;
}
//方式一
Integer reduce = list.stream().reduce(0, (a, b) -> a + b, (a, b) -> a - b);
//方式二
Integer integer = list.stream().reduce((a, b) -> a + b).get();
System.out.println(i);
System.out.println(reduce);
System.out.println(integer);
}
14,终端操作,collect,归约操作的方式collect,收集器操作,收集器操作,可以当做是一种更高级的归约操作:
private static void testCollect(List<Temp> temps) {
//转 list
List<String> list = temps.stream().map(Temp::getName).collect(Collectors.toList());
//转 set
Set<Integer> set = temps.stream().map(temp -> temp.getAge()).collect(Collectors.toSet());
//转 map,需要指定key 和 value,Function.identity() 是指当前 Temp 对象本身,当key重复时会报错。
Map<String, Temp> map = temps.stream().collect(Collectors.toMap(Temp::getName, Function.identity()));
Map<String, Temp> map2 = temps.stream().collect(Collectors.toMap(Temp::getName, temp -> temp));
//计算元素中的个数
Long collect = temps.stream().collect(Collectors.counting());
//数据求和 sumingInt,sumingLong,sumingDouble
Integer collect1 = temps.stream().collect(Collectors.summingInt(temp -> temp.getAge()));
Integer collect13 = set.stream().collect(Collectors.summingInt(temp -> temp));
System.out.println(collect1 + " max ---> " + collect13);
//数据求平均值
Double collect2 = temps.stream().collect(Collectors.averagingDouble(Temp::getSalary));
//综合处理,求最大值,最小值,平均值,求和
IntSummaryStatistics collect3 = temps.stream().collect(Collectors.summarizingInt(Temp::getAge));
System.out.println(collect3.getMax());
System.out.println(collect3.getMin());
System.out.println(collect3.getSum());
System.out.println(collect3.getAverage());
System.out.println(collect3.getCount());
//连接字符串
String collect4 = temps.stream().map(temp -> temp.getName()).collect(Collectors.joining());
String collect5 = temps.stream().map(Temp::getName).collect(Collectors.joining(","));
String collect6 = temps.stream().map(Temp::getName).collect(Collectors.joining("--中间分隔符--", "前缀*", "&后缀"));
System.out.println("字符串连接1 --> " + collect4);//张三李四王五王五1王五2
System.out.println("字符串连接2 --> " + collect5);//张三--中间分隔符--李四--中间分隔符--王五--中间分隔符--王五1--中间分隔符--王五2
System.out.println("字符串连接3 --> " + collect6);//前缀*张三--中间分隔符--李四--中间分隔符--王五--中间分隔符--王五1--中间分隔符--王五2&后缀
//maxBy 按照比较器中比较结果筛选 最大值 -- 取出来的不是最大值 或 最小值
Optional<Integer> collect7 = temps.stream().map(Temp::getAge).collect(Collectors.maxBy(Integer::max));
System.out.println("maxBy比较器筛选最大值:" + collect7.get());//18
Optional<Integer> collect8 = temps.stream().map(Temp::getAge).collect(Collectors.minBy(Integer::min));
System.out.println("minBy比较器筛选最小值:" + collect8.get());//21
//归约操作
Optional<Integer> collect9 = temps.stream().map(Temp::getAge).collect(Collectors.reducing((x, y) -> (x + y)));
Integer collect10 = temps.stream().map(Temp::getAge).collect(Collectors.reducing(0, (x, y) -> (x + y)));
System.out.println("归约操作1:" + collect9.get());
System.out.println("归约操作2:" + collect10);
//分组操作
Map<Integer, List<Temp>> collect11 = temps.stream().collect(Collectors.groupingBy(Temp::getAge));
collect11.forEach((k,v)-> System.out.println("分组操作:" + k + " " + v.size()));
//分区操作
Map<Boolean, List<Integer>> collect12 = temps.stream().map(Temp::getAge).collect(Collectors.partitioningBy(age -> age > 20));
collect12.forEach((k,v)-> System.out.println("分区操作:" + k + " " + v.size()));
}
注意事项:使用stream的toMap()函数时,当key重复,系统会报错相同的key不能形成一个map,那么需要解决这个问题,一:相同key的情况下,丢弃重复的只保留一个,二:相同key的情况下,把value变成list,形成Map(Object,List)的形式。
报错写法:
String[] arr = {"1@1","2@2","3@3","1@4","5@5","6@6"};
// 重复 key 报错的写法
Map<String, String> collect = Stream.of(arr).map(temp -> temp.split("@")).collect(Collectors.toMap(str -> str[0], str -> str[1]));
报错内容:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 1
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1253)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.example.test.java_base.java8.Java8Test.toMapDuplicateKey(Java8Test.java:20)
at com.example.test.java_base.java8.Java8Test.main(Java8Test.java:12)
处理方式一:后一个 value 覆盖前一个 value 值:
private static void toMapDuplicateKey() {
String[] arr = {"1@1","2@2","3@3","1@4","5@5","6@6"};
Map<String, String> collect = Stream.of(arr).map(temp -> temp.split("@"))
.collect(Collectors.toMap(str -> str[0], str -> str[1], (v1,v2) -> v2));
System.out.println(collect); // 打印结果:{1=4, 2=2, 3=3, 5=5, 6=6}
}
处理方式二:当 key 重复,使用 “旧值,新值” 的方式处理:
private static void toMapDuplicateKey2(List<Temp> temps) {
List<Temp> temps = new ArrayList<>();
temps.add(new Temp("张三", 18, 800, "2017/06/15 14:11:17"));
temps.add(new Temp("李四", 19, 1500, "2017/06/14 14:11:17"));
temps.add(new Temp("王五", 25, 2000, "2017/06/16 13:11:17"));
temps.add(new Temp("李四2", 19, 900, "2017/06/16 14:10:17"));
temps.add(new Temp("王五2", 21, 1800, "2017/06/17 14:11:17"));
temps.add(new Temp("王五3", 19, 1800, "2017/06/17 14:11:17"));
Map<Integer, String> collect = temps.stream().collect(Collectors.toMap(
temp -> temp.getAge(),
temp -> temp.getName(),
(oldValue, newValue) -> oldValue + "," + newValue
));
System.out.println(collect); // 打印结果:{18=张三, 19=李四,李四2,王五3, 21=王五2, 25=王五}
// 覆盖值的写法
Map<String, Temp> accountMap = accountBatch.stream().collect(Collectors.toMap(Temp::getName, v1 -> v1, (v1,v2) -> v1));
// 上面的写法等同于
Map<String, Temp> accountMap = accountBatch.stream().collect(Collectors.toMap(temp -> temp.getAge(), v1 -> v1, (v1,v2) -> v1));
}
处理方式三:当key重复,使用 list 集合收集:
private static void toMapDuplicateKey2() {
List<Temp> temps = new ArrayList<>();
temps.add(new Temp("张三", 18, 800, "2017/06/15 14:11:17"));
temps.add(new Temp("李四", 19, 1500, "2017/06/14 14:11:17"));
temps.add(new Temp("王五", 25, 2000, "2017/06/16 13:11:17"));
temps.add(new Temp("李四2", 19, 900, "2017/06/16 14:10:17"));
temps.add(new Temp("王五2", 21, 1800, "2017/06/17 14:11:17"));
Map<Integer, List<String>> collect = temps.stream().collect(Collectors.toMap(
Temp::getAge,
temp -> {
List<String> list = new ArrayList<String>();
list.add(temp.getName());
return list;
},
(List<String> oldList, List<String> newList) -> {
oldList.addAll(newList);
return oldList;
}));
System.out.println(collect); // 打印结果: {18=[张三], 19=[李四, 李四2], 21=[王五2], 25=[王五]}
}
完整的代码,如下:
package com.test.testjavaee;
import lombok.Data;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @date 2018/7/24 16:45
* @since
*/
public class Java8_stream {
public static void main(String[] args) {
List<Temp> temps = new ArrayList<>();
temps.add(new Temp("张三", 18, 800, "2017/06/15 14:11:17"));
temps.add(new Temp("李四", 19, 1500, "2017/06/14 14:11:17"));
temps.add(new Temp("王五", 25, 2000, "2017/06/16 13:11:17"));
temps.add(new Temp("王五1", 19, 900, "2017/06/16 14:10:17"));
temps.add(new Temp("王五2", 21, 1800, "2017/06/17 14:11:17"));
//**1,创建 stream 的几种方式
// testCreateStream();
//**2,filter,中间操作,对list 集合进行条件判断,留下满足条件的数据。
// testFilter();
//**3,map,中间操作
// testMap();
//4,flatMap 合并两个流
// testFlatMap();
//5,distinct,中间操作,去重
testDistinact(temps);
//6,peek,中间操作
// testPeek(temps);
//7,spike,limit,中间操作
// testSpikeAndLimit();
// =================================================================
//**8,接口终端操作,forEach,forEachOrdered
// testForEach(temps);
//9,终端操作 toArray,把集合转换成数组
// testToArray(temps);
//10,终端操作,min,max
// testMinAndMax(temps);
//11,终端操作,findFirst,findAny
// testFindFirstAndFindAny(temps);
//12,终端操作,count,anyMatch,allMatch,noneMatch
// test_count_anyMatch_allMatch_noneMatch();
//13,终端操作,reduce,可以用来累计求和等操作
// testReduce();
//**14,终端操作,collect,归约操作的方式collect,收集器操作,收集器操作,可以当做是一种更高级的归约操作;
testCollect(temps);
//在java8中,很多的stream的终端操作,都返回了一个Optional<T>对象,这个对象,是用来解决空指针的问题,而产生的一个类
}
private static void testCollect(List<Temp> temps) {
//转 list
List<String> list = temps.stream().map(Temp::getName).collect(Collectors.toList());
//转 set
Set<Integer> set = temps.stream().map(temp -> temp.getAge()).collect(Collectors.toSet());
//转 map,需要指定key 和 value,Function.identity() 是指当前 Temp 对象本身,当key重复时会报错。
Map<String, Temp> map = temps.stream().collect(Collectors.toMap(Temp::getName, Function.identity()));
Map<String, Temp> map2 = temps.stream().collect(Collectors.toMap(Temp::getName, temp -> temp));
//计算元素中的个数
Long collect = temps.stream().collect(Collectors.counting());
//数据求和 sumingInt,sumingLong,sumingDouble
Integer collect1 = temps.stream().collect(Collectors.summingInt(temp -> temp.getAge()));
Integer collect13 = set.stream().collect(Collectors.summingInt(temp -> temp));
System.out.println(collect1 + " max ---> " + collect13);
//数据求平均值
Double collect2 = temps.stream().collect(Collectors.averagingDouble(Temp::getSalary));
//综合处理,求最大值,最小值,平均值,求和
IntSummaryStatistics collect3 = temps.stream().collect(Collectors.summarizingInt(Temp::getAge));
System.out.println(collect3.getMax());
System.out.println(collect3.getMin());
System.out.println(collect3.getSum());
System.out.println(collect3.getAverage());
System.out.println(collect3.getCount());
//连接字符串
String collect4 = temps.stream().map(temp -> temp.getName()).collect(Collectors.joining());
String collect5 = temps.stream().map(Temp::getName).collect(Collectors.joining(","));
String collect6 = temps.stream().map(Temp::getName).collect(Collectors.joining("--中间分隔符--", "前缀*", "&后缀"));
System.out.println("字符串连接1 --> " + collect4);//张三李四王五王五1王五2
System.out.println("字符串连接2 --> " + collect5);//张三--中间分隔符--李四--中间分隔符--王五--中间分隔符--王五1--中间分隔符--王五2
System.out.println("字符串连接3 --> " + collect6);//前缀*张三--中间分隔符--李四--中间分隔符--王五--中间分隔符--王五1--中间分隔符--王五2&后缀
//maxBy 按照比较器中比较结果筛选 最大值 -- 取出来的不是最大值 或 最小值
Optional<Integer> collect7 = temps.stream().map(Temp::getAge).collect(Collectors.maxBy(Integer::max));
System.out.println("maxBy比较器筛选最大值:" + collect7.get());//18
Optional<Integer> collect8 = temps.stream().map(Temp::getAge).collect(Collectors.minBy(Integer::min));
System.out.println("minBy比较器筛选最小值:" + collect8.get());//21
//归约操作
Optional<Integer> collect9 = temps.stream().map(Temp::getAge).collect(Collectors.reducing((x, y) -> (x + y)));
Integer collect10 = temps.stream().map(Temp::getAge).collect(Collectors.reducing(0, (x, y) -> (x + y)));
System.out.println("归约操作1:" + collect9.get());
System.out.println("归约操作2:" + collect10);
//分组操作
Map<Integer, List<Temp>> collect11 = temps.stream().collect(Collectors.groupingBy(Temp::getAge));
collect11.forEach((k,v)-> System.out.println("分组操作:" + k + " " + v.size()));
//分区操作
Map<Boolean, List<Integer>> collect12 = temps.stream().map(Temp::getAge).collect(Collectors.partitioningBy(age -> age > 20));
collect12.forEach((k,v)-> System.out.println("分区操作:" + k + " " + v.size()));
}
private static void testReduce() {
//reduce 是一种归约操作,将流归约成一个值的操作叫做归约操作,用函数式编程语言的术语来说,这种称为折叠(fold);
List<Integer> list = Stream.iterate(1, x -> ++x).limit(10).collect(Collectors.toList());
//jdk1.7 的做法
Integer i = 0;
for (Integer integer : list){
i += integer;
}
//方式一
Integer reduce = list.stream().reduce(0, (a, b) -> a + b, (a, b) -> a - b);
//方式二
Integer integer = list.stream().reduce((a, b) -> a + b).get();
System.out.println(i);
System.out.println(reduce);
System.out.println(integer);
}
private static void test_count_anyMatch_allMatch_noneMatch() {
List<String> list = Arrays.asList("a", "a", "a", "a", "b", "c", "a");
//anyMatch表示,判断的条件里,任意一个元素成功,返回true
boolean b = list.stream().anyMatch(temp -> "a".equals(temp));
//allMatch表示,判断条件里的元素,所有的都是,返回true
boolean b1 = list.stream().allMatch(temp -> "a".equals(temp));
//noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
boolean b2 = list.stream().noneMatch(temp -> "a".equals(temp));
//返回集合的记录数
long count = list.stream().count();
long count1 = list.stream().filter(temp -> "a".equals(temp)).count();
System.out.println(b);
System.out.println(b1);
System.out.println(b2);
System.out.println(count);
System.out.println(count1);
}
private static void testFindFirstAndFindAny(List<Temp> temps) {
/*findFirst和findAny,通过名字,就可以看到,
对这个集合的流,做一系列的中间操作后,
可以调用findFirst,返回集合的第一个对象,
findAny返回这个集合中,取到的任何一个对象;
*/
List<String> list = temps.stream().map(Temp::getName).collect(Collectors.toList());
//未进行中间操作
Optional<String> first = list.stream().findFirst();
String s = first.get();
Optional<String> any = list.stream().findAny();
String s1 = any.get();
Optional<String> first1 = list.parallelStream().findFirst();
String s2 = first1.get();
String s3 = list.parallelStream().findAny().get();
System.out.println(s + " ====> " + s2);
System.out.println(s1 + " =====> " + s3);
System.out.println("======================================");
//进行中间操作
String s4 = list.stream().filter(temp -> !"李四".equals(temp)).findFirst().get();
String s5 = list.stream().filter(temp -> !"李四".equals(temp)).findAny().get();
String s6 = list.parallelStream().filter(temp -> !"李四".equals(temp)).findFirst().get();
String s7 = list.parallelStream().filter(temp -> !"李四".equals(temp)).findAny().get();
System.out.println(s4 + " -----> " + s6);
System.out.println(s5 + " -----> " + s7);
}
private static void testMinAndMax(List<Temp> temps) {
List<Double> list = temps.stream().map(Temp::getSalary).collect(Collectors.toList());
//方式一,Function.identity()
Optional<Double> min = list.stream().min(Comparator.comparing(Function.identity()));
Double d = min.get();
System.out.println("min 方式一 --->" + d);
//方式二
Double d2 = list.stream().min((o1, o2) -> o1.compareTo(o2)).get();
System.out.println("min 方式二 --->" + d2 + "\n");
Double d3 = list.stream().max(Comparator.comparing(Function.identity())).get();
System.out.println("max 方式一 --->" + d3);
Double d4 = list.stream().max((o1, o2) -> o1.compareTo(o2)).get();
System.out.println("max 方式二 --->" + d4 + "\n");
System.out.println(String.format("min:%s;max:%s", d, d3));
}
private static void testToArray(List<Temp> temps) {
List<Integer> list = temps.stream().map(temp -> temp.getAge()).collect(Collectors.toList());
//使用 stream 把集合转换成数组
//方式一,指明类型
Integer[] integers = list.stream().toArray(Integer[]::new);
System.out.print(integers.toString() + " ");
//方式二
Integer[] integers1 = list.stream().toArray(temp -> new Integer[list.size()]);
//方式三,未指明类型
Object[] objects = list.stream().toArray();
//使用 list 自带的 toArray 方法进行转换
Integer[] integers2 = list.toArray(new Integer[list.size()]);
Object[] objects1 = list.toArray();
}
private static void testForEach(List<Temp> temps) {
List<Integer> list = temps.stream().map(Temp::getAge).collect(Collectors.toList());
//串行执行
list.stream().forEach(age -> System.out.print(age + " ") );
System.out.println();
list.stream().forEachOrdered(age-> System.out.print(age + " "));
System.out.println();
//parallelStream 并行执行,forEach 输出的顺序会乱,forEachOrdered 不会乱
list.parallelStream().forEach(age-> System.out.print(age + " "));
System.out.println();
list.parallelStream().forEachOrdered(age-> System.out.print(age + " "));
}
private static void testSpikeAndLimit() {
//无限流,从 1 开始。
Stream.iterate(1, x -> ++x).skip(5).limit(10).forEach(temp-> System.out.print(temp + " "));
}
private static void testPeek(List<Temp> temps) {
//方式一
Stream<Temp> peek = temps.stream().filter(temp ->
temp.getAge() > 20
).peek(temp -> {
temp.setSalary(temp.getSalary() * 2);
});
//方式二
// Stream<Temp> peek = temps.stream().filter(temp -> {
// return temp.getAge() > 20;
// }).peek(temp -> {
// temp.setSalary(temp.getSalary() * 2);
// });
peek.forEach(temp -> System.out.println(temp.getSalary()));
}
private static void testDistinact(List<Temp> temps) {
//去重,排序
//默认为升序,
//根据某个字段升序排序, .sorted(Comparator.comparing(Temp::getAge))
Arrays.asList(1, 4, 1, 2, 3).stream().distinct().sorted().forEach(i -> System.out.print(i));
System.out.println();
//设置为降序
Arrays.asList("1", "4", "1", "2", "3").stream().distinct().sorted(Comparator.reverseOrder()).forEach(str -> System.out.print(str));
System.out.println();
//根据某个字段降序排序, .sorted(Comparator.comparing(Temp::getBrithday).reverseOrder())
List<Temp> collect = temps.stream().sorted(Comparator.comparing(Temp::getBrithday).reversed()).collect(Collectors.toList());
collect.forEach(temp -> System.out.println(temp.toString()));
}
private static void testFlatMap() {
String[] strings = {"aaa", "bbb", "ccc"};
String[] strings2 = {"d", "e", "f"};
Arrays.stream(strings).map(str -> str.split("")).flatMap(Arrays::stream).forEach(str-> System.out.print(str));
}
private static void testMap() {
/*作用:
可以用来对对象也可以是基本数据类型也可以是引用类型,进行处理后返回
可以用来对对象中的某个元素进行操作并返回,如只返回该对象中的某个字段
可以对当前对象进行转换,如把 json 转成对象。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
这个接口,接收一个泛型T,返回泛型R,map函数的定义,返回的流,表示的泛型是R对象,这个表示,调用这个函数后,可以改变返回的类型,
*/
Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 3});
stream.map(str -> Integer.toString(str)).forEach(i -> {
System.out.print(i + " ");
});
List<Temp> temps = Arrays.asList(new Temp("a", 21, 800), new Temp("b", 25, 1800), new Temp("c", 19, 2000));
//方式一 .map(当前对象 -> 对当前对象进行操作并返回操作的结果)
temps.stream().map(temp -> temp.getName()).forEach(name -> System.out.print(name));
System.out.println();
//方式二
temps.stream().map(Temp::getName).forEach(name -> System.out.print(name));
System.out.println();
temps.stream().map(temp -> temp.getName().toUpperCase()).collect(Collectors.toList()).forEach(System.out::print);
System.out.println();
temps.stream().map(Temp::getName).map(temp -> (temp + "_").toUpperCase()).collect(Collectors.toList()).forEach(System.out::print);
System.out.println();
temps.stream().filter(temp -> temp.getAge() > 20).map(temp -> temp.getAge() * 2).collect(Collectors.toList()).forEach(temp-> System.out.print(temp + " "));
}
private static void testFilter() {
//.filter(当前对象 -> )
Arrays.stream(new String[]{"a","b","c"}).filter(temp -> "c".equals(temp)).forEach(System.out::print);
System.out.println();
}
private static void testCreateStream(){
System.out.println("执行创建stream 方法=====================");
String[] aa = {"a", "b", "c"};
//方式一
Arrays.stream(aa).forEach(System.out::print);
System.out.println();
//方式二
Stream.of(aa).forEach(System.out::print);
System.out.println();
//方式三,最常用的一种方式
Arrays.asList(aa).stream().forEach(System.out::print);
System.out.println();
//方式四
Stream.iterate(0, x -> x + 1).limit(10).forEach(temp -> System.out.print(temp));
System.out.println();
}
}
@Data
class Temp{
String name;
int age;
double salary;
String brithday;
public Temp(){}
public Temp(String name){
this.name = name;
}
public Temp(String name, int age, double salary){
this.name = name;
this.age = age;
this.salary = salary;
}
public Temp(String name, int age, double salary, String brithday){
this.name = name;
this.age = age;
this.salary = salary;
this.brithday = brithday;
}
}