Lambda表达式
jdk8 Lambda新特性我就不多说了,实战最重要。
Lambda详细可以参考:http://www.runoob.com/java/java8-functional-interfaces.html
还有就是 时间戳 不要在用以前的那种
Date date = new Date(); 这个对象是不可以改变的 做加法操作
JDK1.8 新特性 只有年月日没有时分秒
class TestLambda { public static void main(String[] args){ Date date = new Date(); System.out.println(date.getYear()+1); //jdk8 只有年月日的 LocalDate day = LocalDate.now(); System.out.println(day); day.plusDays(1); System.out.println(day); //jdk8 有时分秒的 LocalDateTime time = LocalDateTime.now; System.out.println(time); } }
lambda函数式编程(讲究输入输出)
告别匿名内部类,同时提升了对结合、框架的迭代、遍历、过滤数据的操作
参数不用指定类型 自动推断
代码量少 简洁
开启线程:
class TestLambda { public static void main(String[] args){ new Thread(()->{ System.out.println("thread run"); }).start(); } }
简洁还可以自己推断类型:排序
class TestLambda { public static void main(String[] args){ List<String> strs = Arrays.asList("111","22","333","44444"); Collections.sort(strs,(a,b)-> a.length()-b.length()); System.out.println(strs); } }
更容易实现并行 实例略
Lambda 处处都是泛型 用Stream api 经常用到
Lambda 使用场景 任何有函数接口的地方都可以用的
函数式接口: 只有一个抽象方法的接口是函数式接口
比如一个interface 里面有一个抽象方法就是 函数式接口
Object 里面的方法 hashcode 方法 也不算的
jdk有个注解 标注接口是 函数式接口 @FunctionalInterface
小结:
default static 和Object的方法 除外 其他的抽象方法只有一个!
@FunctionalInterface public interface TestLambda { int delete(); public int hashCode(); default int insert(){ return 1; } static int update(){ return 1; } }
jdk 1.8之前的
runnable 就是一个典型的函数式接口
Callable<T> 也是
Comparator<T> 也是
jdk中,点开rt.jar 里面有的是 函数式接口遍地都是
其中的非常重要的有用的函数式接口:
Supplier 代表一个输出
Consumer代表一个输入
BigConsumer 代表连个输入
Function 代表一个输入,一个输出(一般输入和输出是不同类型的)
UnaryOperator代表一个输入,一个输出(输入和输出类型是相同类型的)
BiFunction 代表两个输入 一个输出(一般输入和输出是不同类型的)
BinaryOperator 代表两个输入,一个输出(输入和输出是相同类型的)
java8中为接口新增了一项功能:定义一个或者更多个静态方法。用法和普通的static方法一样
在接口中,增加default方法, 是为了既有的成千上万的Java类库的类增加新的功能, 且不必对这些类重新进行设计。 比如, 只需在Collection接口中
增加default Stream stream(), 相应的Set和List接口以及它们的子类都包含此的方法, 不必为每个子类都重新copy这个方法。
Lambda 表达式
是对象,一个函数式接口的实例。 普通的接口,非函数式的接口不能使用lambda表达式
语法:
参数 -> body体(实现抽象方法的逻辑体)
Runnable = () -> System.out.println("yeah")
即: args->expr
或者 (Object...args) -> {函数式接口抽象方法实现逻辑}
()里面参数的个数,根据函数式接口里面抽象方法的参数个数来决定
当只有一个参数的时候,()可以省略
当expr逻辑非常简单到时候,{}和return可以省略
无参数无返回值
public class Test19 { public static void main(String[] args) { Runnable r1 = new Runnable() { @Override public void run() { System.out.println("normal"); } }; r1.run(); Runnable r2 = ()->{ System.out.println("run lambda"); }; r2.run(); //也可以这么简写 Runnable r3 = ()-> System.out.println("run lambda simple"); r3.run(); } }
无参数有返回值
public class Test19 { public static void main(String[] args) throws Exception { Callable<String> c1 = new Callable<String>() { @Override public String call() { return "normal"; } }; System.out.println(c1.call()); Callable<String> c2 =()->{return "Lambda";}; System.out.println(c2.call()); Callable<String> c3 =()-> "lambda simple"; System.out.println(c3.call()); } }
有参无返回值的
public class Test19 { public static void main(String[] args) throws Exception { UserMapper userMapper1 = new UserMapper() { @Override public void insert(String um) { System.out.println("insert"+um); } }; UserMapper userMapper2 = (String um)->{ System.out.println("insert"+um); }; UserMapper userMapper3 = (um)->{ System.out.println("insert"+um); }; userMapper1.insert("u1"); userMapper2.insert("u2"); userMapper3.insert("u3"); } } interface UserMapper{ void insert(String um); }
有参有返回值
public class Test19 { public static void main(String[] args) throws Exception { OrderMapper orderMapper1 = new OrderMapper() { @Override public int insert(String um) { return 1; } }; OrderMapper orderMapper2 = (num)->{return 2;}; OrderMapper orderMapper3=(String num)->{return 3;}; OrderMapper orderMapper4=(num)-> 4 ; OrderMapper orderMapper5=(String num)-> 5 ; System.out.println(orderMapper1.insert("test")); System.out.println(orderMapper2.insert("test")); System.out.println(orderMapper3.insert("test")); System.out.println(orderMapper4.insert("test")); System.out.println(orderMapper5.insert("test")); } } interface OrderMapper{ int insert(String um); }
public class Test19 { public static void main(String[] args) throws Exception { Function<Integer,Integer> function1 =a->{ int sum = 0; for (int i=1; i<=a; i++){ sum+=i; } return sum; }; System.out.println(function1.apply(10)); } }
注意当省略大括号和return时候 注意方法的返回值和没有返回值
抽象方法有返回值 实现类必须给 如果没有返回值可以给也可以不给
总结如何写lambda?
1 看参数
2 看返回值
public class Test19 { public static void main(String[] args) throws Exception { //两个参数一个返回值 BiFunction<String,String,Integer> bf=(a,b)->{ return a.length()+b.length(); }; System.out.println(bf.apply("abc","dsdf")); } }
先定一个框架
( ) -> { }
然后根据参数调整之
(a,b)
然后就是返回值类型
{
代码逻辑;
return 1
}
最终:
(a,b)->{
代码逻辑;
return 1;}
Lambda 表达式生成一个函数式接口的实例
Runnable 就是个函数式接口
public class Test19 { public static void main(String[] args) throws Exception { Function<String,String> fn = (str)->str.toUpperCase(); System.out.println(fn.apply("toov5")); } }
public class Test19 { public static void main(String[] args) throws Exception { Consumer<String> c = arg->{ System.out.println(arg); }; c.accept("testLambda"); } }
这两个lambda表达式特点:
仅仅引用了输入参数对象的实例方法 (xxx.toUpcase() )
方法的引用:
方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用方法引用
public class Test19 { public static void main(String[] args) throws Exception { Consumer<String> c1 = arg->{ System.out.println(arg); }; c1.accept("testLambda"); Consumer<String> c2 = arg->{ System.out.println(arg); }; c2.accept("testGoOn"); } }
将上面改成方法引用!
首先要知道方法引用的分类:
类型 |
语法 |
对应的lambda表达式 |
静态方法引用 |
类名::staticMethod |
(args) -> 类名.staticMethod(args) |
实例方法引用 |
inst::instMethod |
(args) -> inst.instMethod(args) |
对象方法引用 |
类名::instMethod |
(inst,args) ->类名.instMethod(args) |
构造方法引用 |
类名::new |
(args) -> new 类名(args) |
静态方法引用:
如果函数式接口的实现恰好可以通过调用一个静态方法来实现,那么就可以使用静态方法引用
无输入参数的情况:
public class Test19 { public static String put(){ return "hello Lambda"; } public static void main(String[] args) { Supplier<String> s1 = () -> Test19.put(); //可以如下使用 仅仅调用了静态方法 没有做其他事情 Supplier<String> s2 = Test19::put; System.out.println(s2.get()); Supplier<String> s3 = Fun::ret; System.out.println(s3.get()); } } //任意类的静态方法 class Fun{ public static String ret(){ System.out.println("ret function"); return "hello"; } }
有输入参数的情况:
public class Test19 { public static void con(Integer size){ System.out.println(size+"Length"); } public static void main(String[] args) { //lambda 表达式调用某个类的静态方法 Consumer<Integer> con = Test19::con; //没有括号哦 仅仅是引用 而不是执行 con.accept(123); } }
有输入也有输出的情况:
public class Test19 { public static String toUpperCase(String str){ return str.toUpperCase(); } public static Integer len(String str1, String str2){ return str1.length()+str2.length(); } public static void main(String[] args) { Function<String,String> function = str->str.toUpperCase(); Function<String,String> function1 = str -> str.toUpperCase(); Function<String,String> function2 = str -> Test19.toUpperCase(str); //方法引用 Function<String,String> function3 = Test19::toUpperCase; //调用下 System.out.println(function3.apply("toov5Test")); //或者 Function<String,String> f4 = Fun::toUpperCase; System.out.println(f4.apply("testToov5")); BiFunction<String,String,Integer> bf1 = (s1,s2)->s1.length()+s2.length(); BiFunction<String,String,Integer> bf2 = (s1,s2)->Test19.len(s1,s2); //改成lambda方法引用 BiFunction<String,String,Integer> bf3 =Test19::len; System.out.println(bf3.apply("toov5","java")); } } class Fun{ //类的静态方法 public static String toUpperCase(String str){ return str.toUpperCase(); } }
以上为静态方法引用
下面是实例方法引用:
如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用
public class Test19 { public String put(){ return "toov5"; } public void con(Integer size){ System.out.println("size"+size); } public static void main(String[] args) { Supplier<String> s1 = ()->new Test19().put(); Supplier<String> s2 = ()->{return new Test19().put();}; Supplier<String> s3 = new Test19()::put; //对象实例方法的引用 System.out.println(s3.get()); Test19 test19 = new Test19(); Consumer<Integer> c1 = (size)-> new Test19().con(size); Consumer<Integer> c2 = new Test19()::con; Consumer<Integer> c3 = test19::con; c1.accept(100); c2.accept(200); c3.accept(300); } }
如下:
public class Test19 { public String put(String t){ System.out.println("test"); return "toov5"; } public void con(String s){ Function<String,String> function = this::put; System.out.println(function.apply("toov5")); } public static void main(String[] args) { Consumer<String> con = new Test19()::con; con.accept("tName"); } }
还可以这么写 调用当前实例的方法
public class Test19 { public String put(String t){ System.out.println("test"); return "toov5"; } public void con(String s){ Function<String,String> function = this::put; System.out.println(function.apply("toov5")); //当前实例的方法 } public static void main(String[] args) { Consumer<String> con = new Test19()::con; con.accept("tName"); } }
还可以调用父类的
class Base{ public String upper(String str){ return str.toUpperCase(); } } public class Test19 extends Base{ public void con(String s){ Function<String, String> upper = super::upper; System.out.println(upper.apply(s)); } public static void main(String[] args) { Consumer<String> con = new Test19()::con; con.accept("toov5TestLambda"); } }
对象方法引用:
抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用
抽象方法必须要有参数!
抽象方法没有输入参数,不能使用对象方法引用
比如下面的函数式接口
Runnable run = () -> {}
Closeable c = () - > {};
Supplier<String> s = () - > "";
一个参数类型
public class Test19 extends Base{ public static void main(String[] args) { Consumer<Toov5> c =(Toov5 toov5)-> new Toov5().t(); Consumer<Toov5> t = Toov5::t; c.accept(new Toov5()); t.accept(new Toov5()); } } class Toov5{ public void t(){ System.out.println("method T"); } }
两个参数类型
改写成:
public class Test19 extends Base{ public static void main(String[] args) { //两个条件的 BiConsumer<Toov5,String> consumer1 = (toov5,str)->new Toov5().foo(str); BiConsumer<Toov5,String> consumer2 = Toov5::foo; //三个条件的 BiFunction<Prod,String,Integer> bf1 =(p,s) -> new Prod().fun(s); BiFunction<Prod, String, Integer> fun = Prod::fun; } } class Prod{ public Integer fun(String s){ return 1; } }
构造方法引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
public class Test19 { public static void main(String[] args) { Supplier<Person> s1 =()-> new Person(); //可以这么写 Supplier<Person> s2 = Person::new; s1.get(); s2.get(); } } class Person{ public Person(){ System.out.println("person"); } }
public class Test19 { public static void main(String[] args) { Supplier<Thread> s1 = Thread::new; Supplier<List> s2 = ArrayList::new; Supplier<String> s3 = String::new; } }
如果只有有参的构造函数:
public class Test19 { public static void main(String[] args) { Consumer<Integer> c = (age) ->new Acount(age); // //可以这么写 Consumer<Integer> consumer = Acount::new; c.accept(11); //输入字符串输出int Function<String, Integer> fu = (str)-> Integer.valueOf(str); Function<String, Integer> function = Integer::valueOf; function.apply("2"); } } class Acount{ public Acount(int age){ System.out.println(age); } }
Stream
Stream是一组用来处理数组、集合的API
特性:
1:不是数据结构,没有内部存储
2:不支持索引访问
3:延迟计算
4:支持并行
5:很容易生成数组或集合(List,Set)
6:支持过滤,查找,转换,汇总,聚合等操作
Stream运行机制
Stream分为 源source,中间操作,终止操作
流的源可以是一个数组、一个集合、一个生成器方法,一个I/O通道等等。
一个流可以有零个和或者多个中间操作,每一个中间操作都会返回一个新的流,供下一个操作使用。一个流只会有一个终止操作
Stream只有遇到终止操作,它的源才开始执行遍历操作
常用的中间操作:
中间操作API
过滤 filter
去重 distinct
排序 sorted
截取 limit、skip
转换 map/flatMap
其他 peek
常用的终止操作
终止操作API
循环 forEach
计算 min、max、count、 average
匹配 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
汇聚 reduce
收集器 toArray collect
Stream的创建
1、通过数组
2、通过集合来
3、通过Stream.generate方法来创建
4、通过Stream.iterate方法来创建
5、其他API创建
有了流之后可以进行中间操作和终止操作
public class Test19 { static void streamFun1(){ String[] arr = {"a","b","c"}; Stream<String> stream =Stream.of(arr); stream.forEach(System.out::println); } static void streamFun2(){ List<String> list = Arrays.asList("a", "b", "c"); Stream<String> stream = list.stream(); stream.forEach(System.out::println); } static void streamFun3(){ Stream<Integer> stream = Stream.generate(()-> 1); stream.limit(10).forEach(System.out::println); } static void streamFun4(){ Stream<Integer> stream = Stream.iterate(1, x -> x + 1); stream.limit(10).forEach(System.out::println); } static void streamFun5() throws Exception{ String str = "abcd"; IntStream chars = str.chars(); // chars.forEach(x-> System.out.println(x)); //也可以使用方法的引用 chars.forEach(System.out::println); //下面是文件流 一行一行读出 Files.lines(Paths.get("d://toov5.java")).forEach(System.out::println); } public static void main(String[] args) { // Test19.streamFun1(); // Test19.streamFun2(); // Test19.streamFun3(); Test19.streamFun4(); } }
可以这么玩儿:
public static void main(String[] args) { // Arrays.asList(1,2,3,4,5,6,7,8,9).stream().filter(x->{ // return x%2==0; // }).forEach(System.out::println); Arrays.asList(1,2,3,4,5,6,7,8,9).stream().filter(x-> x%2==0 ).forEach(System.out::println); }
public class Test19 { static void streamFun1(){ String[] arr = {"a","b","c"}; Stream<String> stream =Stream.of(arr); stream.forEach(System.out::println); } static void streamFun2(){ List<String> list = Arrays.asList("a", "b", "c"); Stream<String> stream = list.stream(); stream.forEach(System.out::println); } static void streamFun3(){ Stream<Integer> stream = Stream.generate(()-> 1); stream.limit(10).forEach(System.out::println); } static void streamFun4(){ Stream<Integer> stream = Stream.iterate(1, x -> x + 1); stream.limit(10).forEach(System.out::println); } static void streamFun5() throws Exception{ String str = "abcd"; IntStream chars = str.chars(); // chars.forEach(x-> System.out.println(x)); //也可以使用方法的引用 chars.forEach(System.out::println); //下面是文件流 一行一行读出 Files.lines(Paths.get("d://toov5.java")).forEach(System.out::println); } public static void main(String[] args) { // Arrays.asList(1,2,3,4,5,6,7,8,9).stream().filter(x->{ // return x%2==0; // }).forEach(System.out::println); Arrays.asList(1,2,3,4,5,6,7,8,9).stream().filter(x-> x%2==0 ).forEach(System.out::println); int sum = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().filter(x -> x % 2 == 0 ).mapToInt(x -> x).sum(); System.out.println(sum); //求最大值 Integer max = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().max((a, b) -> a - b).get(); System.out.println(max); Integer min = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().min((a, b) -> a - b).get(); System.out.println(min); //匹配操作 Optional<Integer> result1= Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().filter(x -> x % 2 == 0).findAny(); System.out.println(result1.get()); //排序 过滤 找第一个 Optional<Integer> result2 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().filter(x -> x % 2 == 0).sorted((a, b) -> b - a).findFirst(); System.out.println(result2.get()); //终止操作之前排个序 Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().sorted().forEach(System.out::println); Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().sorted((a,b)-> b-a ).forEach(System.out::println); //字符串的情况 Arrays.asList("sfd", "d", "sdfsdfsdf", "wrwer").stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println); //1到50之内的所有偶数放到集合中 Stream.iterate(1,x->x+1).limit(50).filter(x->x%2==0).forEach(System.out::println); //最终放到一个list中 就不要ForEach了 最终收集成list List<Integer> list = Stream.iterate(1, x -> x + 1).limit(50).filter(x -> x % 2 == 0).collect(Collectors.toList()); System.out.println(list); //去重操作 Arrays.asList(1,2,3,1,3,4).stream().distinct().forEach(System.out::println); Set<Integer> set = Arrays.asList(1, 2, 3, 1, 3, 4).stream().collect(Collectors.toSet()); System.out.println(set); // 忽略最大的前十个 // 50个元素的Stream 然后从高到低进行排序 忽略前10个 List<Integer> integerList1 = Stream.iterate(1, x -> x + 1).limit(50). sorted((a, b) -> b - a).skip(10). collect(Collectors.toList()); System.out.println(integerList1); // 50个元素的Stream 然后从高到低进行排序 忽略前10个 再取10个 List<Integer> integerList2 = Stream.iterate(1, x -> x + 1).limit(50). sorted((a, b) -> b - a).skip(10).limit(10) .collect(Collectors.toList()); System.out.println(integerList2); //转换 String str = "11,22,33,44,55"; int sum1 = Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum();//字符串的stream 转换成Integer int System.out.println(sum1); int sum2 = Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x->x).sum(); System.out.println(sum2); int sum3 = Stream.of(str.split(",")).mapToInt(Integer::valueOf).sum(); System.out.println(sum3); //对象的转换 String str1 = "toov5,test,lambda"; Stream.of(str1.split(",")).map(x->new User(x)).forEach(System.out::println); //可以用构造方法引用 Stream.of(str1.split(",")).map(User::new).forEach(System.out::println); //如果没有构造函数 Stream.of(str1.split(",")).map(x->Person.build(x)).forEach(System.out::println); //静态方法引用 Stream.of(str1.split(",")).map(Person::build).forEach(System.out::println); //peek 中间操作时候 内部调用consumer去消费 就跟记录日志一样 String str4 = "11,22,33,44,55"; int sum4 = Stream.of(str4.split(",")).peek(System.out::println).mapToInt(x -> Integer.valueOf(x)).sum(); System.out.println(sum4); } } class User{ private String name; public User(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } } class Person{ private String name; public static Person build(String name){ Person p = new Person(); p.setName(name); return p; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } }
对于集合和数组的一系列操作!
Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
补充并行流:
public class Test26 { public static void main(String[] args) { Optional<Integer> max = Stream.iterate(1, x -> x + 1) .limit(200).peek(x-> System.out.println(Thread.currentThread().getName())) .max(Integer::compare); System.out.println(max); } }
默认使用的是主线程:
做成并行流
public class Test26 { public static void main(String[] args) { Optional<Integer> max = Stream.iterate(1, x -> x + 1) .limit(200).peek(x-> System.out.println(Thread.currentThread().getName())) .parallel() .max(Integer::compare); System.out.println(max); } }
并行流变成顺序流
public class Test26 { public static void main(String[] args) { Optional<Integer> max = Stream.iterate(1, x -> x + 1) .limit(200).peek(x-> System.out.println(Thread.currentThread().getName())) .parallel() .sequential() .max(Integer::compare); System.out.println(max); } }
内部使用的forkJoinPool 实现并行的
设置并行数量
public class Test26 { public static void main(String[] args) { System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "8"); //也可以启动时候 采用 -D java.util.concurrent.ForkJoinPool.common.parallelism=8 的方式启动设置 Optional<Integer> max = Stream.iterate(1, x -> x + 1) .limit(200).peek(x-> System.out.println(Thread.currentThread().getName())) .parallel() .max(Integer::compare); System.out.println(max); } }
Test:
public class Test26 { private List<Book> books(){ List<Book> books = new ArrayList<>(); books.add(new Book(1,"11",30d,"study",LocalDate.parse("2014-04-03"))); books.add(new Book(2,"22",40d,"learn",LocalDate.parse("2012-05-03"))); books.add(new Book(3,"33",50d,"code",LocalDate.parse("2016-06-07"))); books.add(new Book(4,"44",60d,"language",LocalDate.parse("2018-08-03"))); return books; } @Test public void test1(){ List<Integer> ids1 = books().stream().map(book -> book.getId()).collect(Collectors.toList()); //可以使用方法的引用 List<Integer> ids2 = books().stream().map(Book::getId).collect(Collectors.toList()); System.out.println(ids1); String str = books().stream().map(book -> book.getId() + "").collect(Collectors.joining(",","(",")")); System.out.println(str); String str1 = books().stream().map(book -> "'"+book.getId() + "'").collect(Collectors.joining(",","(",")")); System.out.println(str1); } @Test public void test2(){ List<String> listType = books().stream().map(book -> book.getType()).distinct().collect(Collectors.toList()); System.out.println(listType); //或者不用去重 放入set就OK了 Set<String> setType = books().stream().map(book -> book.getType()).collect(Collectors.toSet()); System.out.println(setType); } @Test public void test3(){ List<Book> collect = books().stream().sorted((book1, book2) -> Double.compare(book1.getPrice(), book2.getPrice())).collect(Collectors.toList()); System.out.println(collect); Comparator<Book> compa =(book1,book2)->Double.compare(book1.getPrice(),book2.getPrice()); //从高到底价格排序 List<Book> collect1 = books().stream().sorted(compa.reversed()).collect(Collectors.toList()); System.out.println(collect1); } }
public class Test26 { private List<Book> books() { List<Book> books = new ArrayList<>(); books.add(new Book(1, "11", 30d, "study", LocalDate.parse("2014-04-03"))); books.add(new Book(2, "22", 40d, "learn", LocalDate.parse("2012-05-03"))); books.add(new Book(3, "33", 50d, "code", LocalDate.parse("2016-06-07"))); books.add(new Book(4, "44", 60d, "language", LocalDate.parse("2018-08-03"))); books.add(new Book(5, "44", 60d, "language", LocalDate.parse("2018-08-07"))); return books; } @Test public void test1() { Comparator<Book> compa = (book1, book2) -> Double.compare(book1.getPrice(), book2.getPrice()); books().stream().sorted(compa.thenComparing((book1, book2) -> book1.getPublishDate().isAfter(book2.getPublishDate()) ? 1 : -1)) .forEach(System.out::println); //简化写法 System.out.println("----"); books().stream().sorted(Comparator.comparing(Book::getPrice)).forEach(System.out::println); books().stream().sorted(Comparator.comparing(Book::getPrice).reversed()).forEach(System.out::println); //反序 //多个排序 System.out.println("more"); books().stream().sorted(Comparator.comparing(Book::getPrice).thenComparing(Comparator.comparing(Book::getPublishDate).reversed())) .forEach(System.out::println); } @Test public void test2() { Map<Integer, String> bookMap1 = books().stream().collect(Collectors.toMap(book -> book.getId(), book -> book.getName())); System.out.println(bookMap1); Map<Integer, String> bookMap2 = books().stream().collect(Collectors.toMap(Book::getId, Book::getName)); System.out.println(bookMap2); } @Test //找出最贵的书 public void test3() { Double avg = books().stream().collect(Collectors.averagingDouble(Book::getPrice)); //平均值 System.out.println(avg); } @Test //找出最贵的书 public void test4() { Double avg = books().stream().collect(Collectors.averagingDouble(Book::getPrice)); //平均值 Optional<Book> resultMax = books().stream().collect(Collectors.maxBy(Comparator.comparing(Book::getPrice))); //价格最高 Optional<Book> resultMin = books().stream().collect(Collectors.minBy(Comparator.comparing(Book::getPrice))); //价格最低 System.out.println(avg); System.out.println(resultMax); System.out.println(resultMin); } @Test public void test5() { Map<String, List<Book>> booksMap = books().stream().collect(Collectors.groupingBy(Book::getType)); booksMap.keySet().forEach(key -> { System.out.println(key); System.out.println(booksMap.get(key)); }); //统计每种类型多少本书 Map<String, Long> typeAndCount = books().stream().collect(Collectors.groupingBy(Book::getType, Collectors.counting()));//groupby 之后进行了收集统计 System.out.println(typeAndCount); //统计每种类型的平均价格 Map<String, Double> typeAndAvgPrice = books().stream().collect(Collectors.groupingBy(Book::getType, Collectors.averagingDouble(Book::getPrice)));//groupby 之后进行了收集统计 System.out.println(typeAndAvgPrice); //统计每种类型的价格总数 Map<String, Double> typeAndTotalPrice = books().stream().collect(Collectors.groupingBy(Book::getType, Collectors.summingDouble(Book::getPrice)));//groupby 之后进行了收集统计 System.out.println(typeAndTotalPrice); //统计每种类型最贵的 Map<String, Optional<Book>> typeAndMaxPrice = books().stream().collect(Collectors.groupingBy(Book::getType, Collectors.maxBy(Comparator.comparing(Book::getPrice))));//groupby 之后进行了收集统计 System.out.println(typeAndMaxPrice); //统计每种类型最便宜的 Map<String, Optional<Book>> typeAndMinPrice = books().stream().collect(Collectors.groupingBy(Book::getType, Collectors.minBy(Comparator.comparing(Book::getPrice))));//groupby 之后进行了收集统计 System.out.println(typeAndMinPrice); } @Test public void testFilter() { books().stream().filter(book -> book.getPrice() > 10).sorted(Comparator.comparing(Book::getPublishDate).reversed()).forEach(System.out::println); } }
关于Java8的foreach
class test1 { public static void main(String[] args){ List<String> list = Arrays.asList("123", "45634", "7892", "abch", "sdfhrthj", "mvkd"); list.stream().forEach(e ->{ if (e.equals("7892")) return; System.out.println(e); }); } }
相当于continue哦