赞
踩
这部分会详细的写jdk1.8新特性,lambda表达式的使用以及stream流的使用。
@FunctionalInterface public interface GreetAble { void greet(); } public class Human { public void sayHello(){ System.out.println("hello"); } } public class Husband { public void marry(RichAble richAble){ richAble.buy(); } public void buyHouse(){ System.out.println("买套房子!"); } public void beHappy(){ // marry(()-> System.out.println("买套房子")); marry(this::buyHouse); } } public class Man extends Human { @Override public void sayHello() { System.out.println("大家好,我是Man!"); } public void method(GreetAble greetAble){ greetAble.greet(); } public void show(){ //method(()->new Human().sayHello()); //使用super代替父类对象 method(super::sayHello); } } public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Person(){ } public Person(String name) { this.name = name; } @Override public String toString() { return this.getClass().getName()+"["+name+"]"; } } @FunctionalInterface public interface RichAble { void buy(); }
/**怎么编写lambda表达式? * 1:看参数 * 2:看返回值 * * 下面的是函数式接口:Object中的方法除外,static方法除外,default方法除外 * jdk1.8之前的一些函数式接口 * java.lang.Runnable * java.util.concurrent.Callable<V> * java.util.Comparator<T> * 下面介绍几个常用的:都在java.util.function包下。 * Supplier<T>:代表一个输出 * Consumer<T>:代表一个输入 * Predicate<T>:输入是T,输出是boolean * BiConsumer<T, U>:代表两个输入 * Function<T, R>:代表一个输入和输出 * BiFunction<T, U, R>:代表两个输入和一个输出。 * UnaryOperator<T>:代表一个输入,一个输出,但是,输入和输出是相同类型。 * BinaryOperator<T>:代表两个输入,一个输出,但是全都是相同类型。 * 其他的都与上面的类似,属于上面的基础上进行的扩展。 * @author 12706 * *1、静态方法的引用 *2、实例方法的引用 *3、对象方法的引用 *4、构造方法的引用 */ public class LambdaExpress { /** * lambda的使用 * 1、看参数 * 2、看返回值 */ @Test public void testLambda() throws Exception { //1、无参无返回值,没有参数括号是不能省的,只有一句代码那么{}就可以省了 Runnable r = () -> System.out.println("hello world"); //2、无参有返回值,只有一句话那么return就可以省了 Callable c = () -> 5; Supplier<String> supplier = () -> "world"; //3、有参无返回值 Consumer<String> consumer = s -> System.out.println(s+":world"); //4、有参有返回值 Function<String,Integer> function = s -> Integer.valueOf(s); r.run(); System.out.println(c.call()); System.out.println(supplier.get()); consumer.accept("tom"); System.out.println(function.apply("101")); } @Test public void testFunction() throws Exception { /* 最基础的:Consumer<T>,Supplier<>,Predicate<T>返回boolean用来测试,比如filter的参数,Function<T,U> 双重:BiConsumer<T,U>两个输入,BiFunction<T, U, R>T,U表示输入,R表示输出 BiPredicate<T, U>两个输入 UnaryOperator<T>:代表一个输入,一个输出,但是,输入和输出是相同类型。继承Function BinaryOperator<T>:代表两个输入,一个输出,但是全都是相同类型。继承BiFunction IntConsumer输入int,IntSupplier输入int,IntFunction<R>输入int,IntPredict输入int 此外还有Doublexxx,Longxxx等,另外还有些感觉用不到的,看源代码即可。 比如ToLongFunction<T>输入是T,输出是Long */ Predicate<String> predicate = str -> str.charAt(0)>'a'; BiConsumer<Integer,String> biConsumer = (num,str)->System.out.println(num+":"+str); BiFunction<Integer,String,Integer> biFunction = (num,str)->Integer.valueOf(str)+num; BiPredicate<Integer,Integer> biPredicate = (num1,num2)->num1>num2+3; } /* 通过对象名引用成员方法 实例方法的引用 使用前提是对象名是已经存在的,成员方法也是已经存在 实例对象的方法能满足函数式接口的实现 就可以使用对象名来引用成员方法 */ public String pop(){ return "hello"; } @Test public void objMethodRefTest(){ Supplier<String> supplier = () -> { LambdaExpress express = new LambdaExpress(); return express.pop(); }; //使用实例方法引用改造 //对象存在 express //方法存在 pop LambdaExpress express = new LambdaExpress(); Supplier<String> supplier2 = express::pop; System.out.println(supplier.get()); System.out.println(supplier2.get()); } /** * 静态方法的引用 */ @Test public void staticMethodRefTest(){ Function<Integer,Integer> f1 = num1 -> Math.abs(num1); //静态方法引用 //类存在 Math //静态方法存在 abs Function<Integer,Integer> f2 = Math::abs; System.out.println(f1.apply(-10)); System.out.println(f2.apply(-10)); } /** * 构造方法的引用 */ @Test public void constructorMethodRefTest(){ Function<String,Person> f1 = name -> new Person(name); Function<String,Person> f2 = Person::new; System.out.println(f1.apply("tom")); System.out.println(f2.apply("tom")); } /** * 通过super引用成员方法 */ @Test public void superMethodRefTest(){ Man man = new Man(); man.show(); } /** * 通过this引用成员方法 */ @Test public void thisMethodRefTest(){ Husband husband = new Husband(); husband.buyHouse(); } /** * 数组的构造器引用 */ @Test public void arrayConsMethodRefTest(){ Function<Integer,int[]> f1 = int[]::new; System.out.println(f1.apply(10).length); } /** * 对象方法的引用 * 抽象方法的第一个参数刚好是实例的类型,后面的参数和实例方法的参数类型一致(即输入参数类型和返回类型一致) * 类名::方法名, 和静态方法引用的写法一样 * 了解就好,前面两个是重点 * 注:要求函数一定要求有参数像Suppier就不行 * 真的很诡异 * */ public void sayHello(String name){ System.out.println("hello,我的名字叫:"+name); } @Test public void abstractMethodRefTest(){ LambdaExpress express = new LambdaExpress(); BiConsumer<LambdaExpress,String> biConsumer = (l, name)->l.sayHello(name); biConsumer.accept(express,"jinBingmin"); BiConsumer<LambdaExpress,String> biConsumer2 = LambdaExpress::sayHello; biConsumer2.accept(express,"Jack"); } }
/** * 创建Stream * @author 12706 * *终止操作: *循环:forEach *计算:max,min,count,average *匹配:anyMatch,allMatch,noneMatch,findFirst,findAny *汇聚:reduce *收集器:toArray,collect * *中间操作: *过滤:filter *去重 :distinct *排序:sorted *截取:limit,skip *转换:map/flatMap *其他:peek * */ public class StreamTest { /** * 1、使用数组创建 int数组不行,泛型会是int[] * stream.of(泛型数组) */ static void gen1(){ Integer[] arr = {1,2,3,4}; Stream<Integer> s = Stream.of(arr); s.forEach(System.out::println); } /** * 2、使用集合 collection.stream() */ static void gen2(){ Stream<Character> stream = Arrays.asList('a', 'b', 'c', 'd').stream(); stream.forEach(System.out::println); } /** * 3、使用generate */ static void gen3(){//不限制10条则会一直打印2 Stream<Integer> stream = Stream.generate(() -> 2).limit(10); stream.forEach(System.out::println); } /** * 4、使用iterate * * @param seed the initial element * @param f a function to be applied to to the previous element to produce * a new element * @return a new sequential {@code Stream} *public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) * */ static void gen4(){ Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(10); stream.forEach(System.out::println); } /** * 5、其他api创建 * @throws IOException */ static void gen5() throws IOException {//打印97-101 String s = "abcde"; IntStream chars = s.chars(); chars.forEach(System.out::println); //一行一行读取 Stream<String> lines = Files.lines(Paths.get("D:\\workspaces\\maven-test2\\src\\main\\resources\\hello.txt")); lines.forEach(System.out::println); } public static void main(String[] args) throws IOException { // StreamTest.gen5(); // *终止操作: // *循环:forEach // *计算:max,min,count,average // *匹配:anyMatch,allMatch,noneMatch,findFirst,findAny // *汇聚:reduce // *收集器:toArray,collect //先介绍下中间操作filter:具有延迟计算特性,必须终止才执行 打印偶数 Arrays.asList(1,2,3,4,5,6).stream().filter(x->x%2==0).forEach(System.out::println); //偶数求和sum() 注:sum()是InteStream才有的函数,Stream是没有的所以要转mapToInt int s = Arrays.asList(1, 2, 3, 4, 5, 6).stream().filter(x -> x % 2 == 0).mapToInt(x -> x).sum(); System.out.println(s); //求偶数最小值(最大值也一样) Optional<Integer> minVal = Arrays.asList(1, 2, 3, 4, 5, 6).stream().filter(x -> x % 2 == 0).min((a, b) -> a - b); if(minVal.isPresent()) System.out.println(minVal.get()); //找出第一个满足条件的 Optional<Integer> fVal = Arrays.asList(1, 2, 3, 4, 5, 6).stream().filter(x -> x % 2 == 0).findFirst();//或者findAny //从1-50里面的所有偶数找出来,放到一个list里面 List<Integer> list = Stream.iterate(1, x -> x + 1).limit(50).filter(x -> x % 2 == 0).collect(Collectors.toList()); // *中间操作: // *过滤:filter // *去重 :distinct // *排序:sorted // *截取:limit,skip // *转换:map/flatMap // *其他:peek // */ //去重排序后找最小的 Optional<Integer> first = Arrays.asList(3, 2, 10, 8, 10, 4, 4).stream().distinct().sorted().findFirst(); //自定义排序 List<String> list1 = Arrays.asList("aaa", "abbdf", "a", "aa").stream().sorted((s1, s2) -> s1.length() - s2.length()).collect(Collectors.toList()); System.out.println(list1); //去重distinct,或者使用toSet List<Integer> list2 = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 5).stream().distinct().collect(Collectors.toList()); Set<Integer> set = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 5).stream().collect(Collectors.toSet()); //skip(10)表示忽略前十个,limit和skip可以用来做分页。 //skip(0),limit(10),表示取第一页,取10个.skip(10)表示第二页 List<Integer> list3 = Stream.iterate(1, x -> x + 1).limit(50).filter(x -> x % 2 == 0).skip(5).limit(5).collect(Collectors.toList()); //转换操作 //将字符串分割,依次转换成int,然后求和 map要求传入的是Function /* * IntStream mapToInt(ToIntFunction<? super T> mapper); * 而ToIntFunction要求实现int applyAsInt(T value);即传入T,返回Integer */ String str = "11,22,33,44,55"; int sum = Stream.of(str.split(",")).map(Integer::valueOf).mapToInt(x -> x).sum(); System.out.println(sum); //或者一步到位 Stream.of(str.split(",")).mapToInt(Integer::valueOf).sum(); //字符串转换为对象map String str2 = "tomcat,nginx,apache,jetty"; Stream.of(str2.split(",")).map(Person::new).forEach(System.out::println); //其他 类似于记个日志,把每个元素取出来做个操作 Stream.of(str2.split(",")).peek(System.out::println).map(Person::new).forEach(System.out::println); } }
public class StreamInAction { static class Book{ private int id; private String name; private double price; private String type; private LocalDate date; public Book(int id,String name,double price,String type,LocalDate localDate){ this.id = id; this.name = name; this.price = price; this.type = type; this.date = localDate; } @Override public String toString() { return this.getClass().getName()+"["+this.getId()+","+this.getName()+","+this.getPrice()+","+this.getType()+","+this.getDate()+"]"; } public String getName() { return name; } public int getId() { return id; } public String getType() { return type; } public double getPrice() { return price; } public LocalDate getDate() { return date; } } private static final List<Book> BOOK_LIST = books(); private static List<Book> books() { List<Book> books = new ArrayList<>(); books.add(new Book(1,"tomcat",50d,"服务器",LocalDate.parse("2014-05-17"))); books.add(new Book(2,"nginx",60d,"服务器",LocalDate.parse("2014-06-17"))); books.add(new Book(3,"java",70d,"编程语言",LocalDate.parse("2013-03-17"))); books.add(new Book(4,"ruby",50d,"编程语言",LocalDate.parse("2014-05-27"))); books.add(new Book(5,"hadoop",80d,"其它",LocalDate.parse("2015-11-17"))); books.add(new Book(6,"spark",45d,"其它",LocalDate.parse("2012-03-17"))); books.add(new Book(7,"storm",55d,"其它",LocalDate.parse("2014-10-17"))); books.add(new Book(8,"kafka",60d,"其它",LocalDate.parse("2016-03-14"))); books.add(new Book(9,"lucene",70d,"其它",LocalDate.parse("2012-05-17"))); books.add(new Book(10,"solr",35d,"其它",LocalDate.parse("2013-05-17"))); books.add(new Book(11,"jetty",90d,"服务器",LocalDate.parse("2014-05-17"))); books.add(new Book(12,"设计模式",60d,"其它",LocalDate.parse("2015-05-17"))); books.add(new Book(13,"数据结构",70d,"其它",LocalDate.parse("2011-05-17"))); books.add(new Book(14,"敏捷开发",50d,"其它",LocalDate.parse("2010-05-17"))); books.add(new Book(15,"算法导论",20d,"其它",LocalDate.parse("1999-05-17"))); books.add(new Book(16,"算法导论",90d,"其它",LocalDate.parse("2017-05-17"))); return books; } @Test public void t1(){ BOOK_LIST.stream().forEach(x-> System.out.println(x.getName())); } //ip地址中的参数转换为map index.do?itemId = 1 & userId = 19202 & token = 1111 @Test public void t2(){ String queryStr = "itemId = 1 & userId = 19202 & token = 1111"; List<String[]> list = Arrays.asList(queryStr.split("&")).stream().map(x -> x.split("=")).collect(Collectors.toList()); list.forEach(x->{ System.out.println(Arrays.toString(x)); }); } @Test public void t3(){ String queryStr = "itemId = 1 & userId = 19202 & token = 1111"; Map<String, String> map = Arrays.asList(queryStr.split("&")).stream().map(x -> x.split("=")).collect(Collectors.toMap(x -> x[0], x -> x[1])); System.out.println(map); } //非常常见 @Test public void t4(){ //把所有书的id取出来放到list中 List<Integer> list = BOOK_LIST.stream().map(x -> x.getId()).collect(Collectors.toList()); System.out.println(list);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] //转换成(1,2,3,4,5)这种形式 这种形式必须转为string String s = BOOK_LIST.stream().map(x -> x.getId() + "").collect(Collectors.joining(",", "(", ")")); System.out.println(s); } @Test public void t5(){ //类型全部取出来并且去重 distinct或者set List<String> list = BOOK_LIST.stream().map(x -> x.getType()).distinct().collect(Collectors.toList()); System.out.println(list); } @Test public void t6(){ //价格由高到低排序 List<Book> list = BOOK_LIST.stream().sorted((a, b) -> (int) (b.getPrice() - a.getPrice())).collect(Collectors.toList()); list.forEach(x-> System.out.println(x.getPrice())); System.out.println("========================="); /** LocalDate a = LocalDate.of(2012, 6, 30);源码这样解释的 * LocalDate b = LocalDate.of(2012, 7, 1); * a.isAfter(b) == false * a.isAfter(a) == false * b.isAfter(a) == true*/ //价格相同的由时间由近到远排 // Compares its two arguments for order. Returns a negative integer, zero, or // a positive integer as the first argument is less than, equal to, or greater // than the second. compare(a,b)方法 也就是说如果是-1就表示前面的比较小,他要排到前面 Comparator<Book> comparator = (a,b)->(int)(b.getPrice()-a.getPrice()); /* 可以这样来看:a.date在b.date后面的时候返回-1,说明此时a排在了b前面,再回来看 a.date此时是after b.date的,说明时间近的a排在了时间远的b前面 符合 */ List<Book> list1 = BOOK_LIST.stream().sorted(comparator.thenComparing((a, b) -> a.getDate().isAfter(b.getDate()) ? -1 : 1)).collect(Collectors.toList()); list1.forEach(x->{ System.out.println(x.getPrice()+":"+x.getDate()); }); System.out.println("================================="); //使用Comparator(comparing要求传入的是Function,代表被排序的类型和按照上面排序,但是它判断不出来传入的类型) List<Book> list2 = BOOK_LIST.stream().sorted(Comparator.comparing((Book b) -> b.getPrice()).reversed().thenComparing((Book b) -> b.getDate())).collect(Collectors.toList()); list1.forEach(x->{ System.out.println(x.getPrice()+":"+x.getDate()); }); } @Test public void t7(){ //转为map,key为数的id Map<Integer, Double> map = BOOK_LIST.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getPrice())); System.out.println(map); } @Test public void t8(){ //求平均价格 OptionalDouble average = BOOK_LIST.stream().map(x -> x.getPrice()).mapToDouble(x -> x).average(); if(average.isPresent()) System.out.println(average.orElseGet(()->0.0)); Double price = BOOK_LIST.stream().collect(Collectors.averagingDouble(x -> x.getPrice())); System.out.println(price); } @Test public void t9(){ //找最大最小 Optional<Book> book = BOOK_LIST.stream().collect(Collectors.maxBy(Comparator.comparing((Book x) -> x.getPrice()))); Optional<Book> book1 = BOOK_LIST.stream().collect(Collectors.minBy(Comparator.comparing((Book x) -> x.getPrice()))); System.out.println(book.get().getPrice()+":"+book1.get().getPrice()); //时间最早的 Optional<Book> book2 = BOOK_LIST.stream().collect(Collectors.maxBy(Comparator.comparing((Book x) -> x.getDate()))); System.out.println(book2.get().getDate()); //最贵的,时间是最早的 Comparator<Book> comparator1 = Comparator.comparing((Book x)->x.getPrice()); Comparator<Book> comparator2 = Comparator.comparing((Book x) -> x.getDate()).reversed(); Optional<Book> book3 = BOOK_LIST.stream().collect(Collectors.maxBy(comparator1.thenComparing(comparator2))); System.out.println(book3.get().getDate()+":"+book3.get().getPrice()); } @Test//分组 public void t10(){ //按照类别分组 对象方法的引用在这里使用到了 Map<String, List<Book>> map = BOOK_LIST.stream().collect(Collectors.groupingBy(Book::getType)); map.entrySet().forEach(x->{ System.out.println(x.getKey()+":"+x.getValue()); }); //分组后计算数量 第二个参数也是传入一个Collectors Map<String, Long> map1 = BOOK_LIST.stream().collect(Collectors.groupingBy(x -> x.getType(), Collectors.counting())); map1.entrySet().forEach(x->{ System.out.println(x.getKey()+":"+x.getValue()); }); //分组后计算价格 对象方法引用看来还是有用的 Map<String, Double> map2 = BOOK_LIST.stream().collect(Collectors.groupingBy(Book::getType, Collectors.summingDouble(Book::getPrice))); map2.entrySet().forEach(x->{ System.out.println(x.getKey()+":"+x.getValue()); }); //分组和计算平均 Map<String, Double> map3 = BOOK_LIST.stream().collect(Collectors.groupingBy(Book::getType, Collectors.averagingDouble(Book::getPrice))); map2.entrySet().forEach(x->{ System.out.println(x.getKey()+":"+x.getValue()); }); //分组后最贵的那本 Map<String, Optional<Book>> map4 = BOOK_LIST.stream().collect(Collectors.groupingBy(Book::getType, Collectors.maxBy(Comparator.comparing((Book x) -> x.getPrice())))); map4.entrySet().forEach(x->{ System.out.println(x.getKey()+":"+x.getValue().get()); }); //分组后最晚出售的 Map<String, Optional<Book>> map5 = BOOK_LIST.stream().collect(Collectors.groupingBy(Book::getType, Collectors.maxBy(Comparator.comparing((Book x) -> x.getDate())))); map5.entrySet().forEach(x->{ System.out.println(x.getKey()+":"+x.getValue().get()); }); } @Test//价格大于80,日期由近到远 public void t11(){ List<Book> list = BOOK_LIST.stream().filter(x -> x.getPrice() >= 80).sorted(Comparator.comparing((Book x) -> x.getDate()).reversed()).collect(Collectors.toList()); list.forEach(System.out::println); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。