JDK 8最大的特点在于lamdda 表达式和Stream 集合处理工具流
/**
* lamdda 表达式的写法
*/
@Test
public void test1(){
//传统写法,匿名内部类
Function<String,String> funOld = new Function<String, String>() {
@Override
public String apply(String t) {
return t;
}
};
//lamdda表达式完整写法
Function<String,String> funAll = (String item)-> {
return item;
};
//参数类型可以省略,因为可以通过泛型推断得出
Function<String,String> fun1 = (item)-> {
return item;
};
//只有一个参数的时候参数扩号可以省略
Function<String,String> fun2 = item-> {
return item;
};
//只有一行代码并且,那么这个行代码的值就是返回值,return和大括号也可以剩余
Function<String,String> fun3 = item->item;
//使用类名或者对象名::方法名字,可以得到对应方法的引用。
Consumer<String> c = System.out::println;
//lamdda 表达式可以看做是 一接口函数的实现。 每一个方法都可以被指定规则的接口函数指向使用 类::实例方法的时候,需要接口函数的第一个参数就是这个 类的实例对象。
//接口函数,有且只有一个抽象方法的接口,这个方法不能是 defualt 和 static的
}
/**
* 最基础的函数接口 和以前常用的一些方法对应关系
*
* 类::实例方法 格式的 lamdda 表达式 等价于 a(类,返回值) 接口函数
*/
@Test
public void test2(){
Goods goods = Goods.randomGoods();
//很多已经存在的方法可以指向对应参数的接口函数,下面三种最基础的函数接口
//Consumer 接口函数,只有一个参数没有返回值
Consumer<String> sysout = System.out::println;
sysout.accept("哇哈哈哈哈");
//Supplier接口函数,只有返回值
Supplier<String> supplier1 = goods::getData;
//Function接口函数,一个参数一个返回值
Function<Double,Long> fun = Math::round;
List<Goods> list = new ArrayList<>();
//Predicate,有一个参数,返回是否,是 function的 特殊情况
Predicate<Goods> predicate = list::contains;
//2个参数的Function
BiFunction<Integer,Integer,Integer> bif = (Integer a,Integer b)->{
return a+b;
};
//实例::实例方法 指向实例方法
Supplier<Long> supplier = goods::getId;
System.out.println(supplier.get());
//类::类方法 等于 a(参数,返回值)
Supplier<Double> f2 = Math::random;
System.out.println( f2.get() );
//类::实例方法 格式的 lamdda 表达式 等价于 a(类,返回值) 接口函数(接口函数或者lamdda表达式的第一个参数是类实例)
Function<Goods,Long> f = Goods::getId;
Function<Goods,Long> ff = item->item.getId();
f.apply( Goods.randomGoods() );
ff.apply( Goods.randomGoods() );
// Comparable.compareTo 接口函数 的实例可以指向 Comparator
Comparator<String> comparator = String::compareTo;
}
/**
* 使用函数接口调用被 lamdda 表达式包裹的对象 get,set 方法
*
* @param
* @return: void
* @Author: ZHANGYUKUN
* @Date: 2022/6/13
*/
@Test
public void test3(){
//使用 lamdda 表达式 在一个对象get方法上包一层
Function<Goods,Long> function = p->{
return p.getId();
};
System.out.println( function.apply(Goods.randomGoods()) );
//使用 lamdda 表达式 在 set 方法上包一层
BiConsumer<Goods,Long> biConsumer = (p1,p2)->{
p1.setId( p2 );
};
Goods goods = Goods.randomGoods();
biConsumer.accept( goods,1L );
System.out.println( goods.getId() );
}
/**
* 构造器引用
*
* @param
* @return: void
* @Author: ZHANGYUKUN
* @Date: 2022/6/13
*/
@Test
public void test4(){
//使用无参构造器
Supplier<Goods> consumer = Goods::new;
System.out.println(JSONObject.toJSONString( consumer.get()));
//使用有参数的构造器
Function<String,Goods> consumer2 = Goods::new;
System.out.println(JSONObject.toJSONString( consumer2.apply("aaaaa") ));
//数组引用
Function<Integer,String[]> consumer3 = String[]::new;
System.out.println(JSONObject.toJSONString( consumer3.apply(10 ) ));
//集合引用
Supplier<List<String>> supplier4 = ArrayList<String>::new;
Function<Integer,List<String>> function5 = ArrayList<String>::new;
//String[] a = new String[]{"1","2","3"};
//String[] b = new String[10];
}
/**
* stram 无限流,按照指定规则,无限生成元素,然后无限循环
*
*/
@Test
public void stram2(){
//Stream
Stream.iterate( 0, item->++item ).limit(100).forEach( System.out::println );
Stream.generate( ()-> Goods.randomGoods() ).limit(100).forEach( System.out::println );
}
/**
* stram 流的常见用法
*
*/
@Test
public void stram3(){
Goods[] array = new Goods[3];
array[0] = Goods.randomGoods();
array[1] = Goods.randomGoods();
array[2] = Goods.randomGoods();
List<String> data = Arrays.asList("1","2","9","0");
List<String> dataNull = Arrays.asList();
List<Goods> list = new ArrayList<>();
//流生产集合
list = list.stream().collect(Collectors.toList() );
//数组转集合
list = Arrays.stream(array).collect(Collectors.toList());
//遍历
Stream.of( array ).forEach( System.out::println );
System.out.println( JSONObject.toJSONString( list ) );
//排序(实现Comparable的可以直接排序,升序)
System.out.println("自带排序:" + Stream.of( 1,3,9,5 ).sorted().collect( Collectors.toList() ) );
//没实现Comparable的元素的集合可以通过传入Comparator实现排序,下面通过ID排序
List<Goods> list2 = Stream.of( array ).sorted(new Comparator<Goods>() {
@Override
public int compare(Goods o1, Goods o2) {
return (int)(o1.getId()-o2.getId());
}
}).collect( Collectors.toList() );
System.out.println("指定排序:" + JSONObject.toJSONString( list2 ) );
//toArray,感觉没什么卵用,类型也错还会报错,保证类型正确的情况下可以把集合转换成数组
String[] ar = data.stream().toArray( item-> {
return new String[item];
} );
System.out.println( "数组:" +ar.length );
//peek 不会终止流的遍历(而且是是用的元素前调用的,调试很好用)
data.stream().peek(System.out::println).forEach(System.out::println);
List<List<Goods>> list22 = new ArrayList<>();
list22.add( Arrays.asList( Goods.randomGoods(),Goods.randomGoods() ) );
list22.add( Arrays.asList( Goods.randomGoods(),Goods.randomGoods() ) );
list22.add( Arrays.asList( Goods.randomGoods(),Goods.randomGoods() ) );
//flatMap把多维度的集合展开成一维集合,例子是把二维集合,展开然后ID求和
Optional<Long> sum = list22.stream().flatMap( item->item.stream() ).map(Goods::getId).reduce( Math::addExact );
System.out.println("求和:" + sum.orElse(-1L) );
//reduce,可以理解成把一个集合的数据合并起来(mapreduce 的 合并类似)
Optional<String> op = data.stream().reduce( (a,b)->a+b );
System.out.println( op.get() );
//Optional 可以减少空指针的辅助类
Optional<String> op2 = dataNull.stream().reduce( (a,b)->a+b );
//取到到就给默认值
System.out.println( op2.orElseGet( ()->"1" ) );
//System.out.println( op2.orElseThrow(()-> new RuntimeException("为空则抛出") ) );
Optional.of("只能包装非空对象");
Optional.ofNullable(null);
//toCollection(把结果装换成任意集合)
List<String> aaa = dataNull.stream().collect( Collectors.toCollection(()->new LinkedList<String>()) );
System.out.println( "toCollection:" + aaa.getClass() );
//summarize(汇总,然后可以知己去平均值,最大最小值,数量等等)
DoubleSummaryStatistics doubleSummaryStatistics = dataNull.stream().collect( Collectors.summarizingDouble( item->Double.valueOf(item) ) );
System.out.println( doubleSummaryStatistics.getMax() );
System.out.println( doubleSummaryStatistics.getMin() );
System.out.println( doubleSummaryStatistics.getAverage() );
//分组(分组的第一个值是分组键,第二个是包装组的容器,第三个是元素集合)
Map<Long,Set<Goods>> map = list2.stream().collect( Collectors.groupingBy( Goods::getId ,LinkedHashMap::new, Collectors.toSet() ) );
System.out.println( map.getClass() );
//分区(相当于只有两个组的分组)
Map<Boolean, List<Goods>> pt = list2.stream().collect( Collectors.partitioningBy((item->true)) );
System.out.println( pt.get(true).size() );
System.out.println( pt.get(false).size() );
//collectingAndThen(先生产集合,然后处理一下),比如分组然后取到所有分组key
Set<Long> keySet = list2.stream().collect( Collectors.collectingAndThen(Collectors.groupingBy( Goods::getId ,LinkedHashMap::new, Collectors.toSet() ), item->item.keySet() ) );
System.out.println( keySet );
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.