JDK1.8新特性

1.Lambda表达式

jdk1.8中Lambda新特性极大的提高编程效率和程序可读性。
通过一个简短的列子来引出Lamda的语法:
通常遍历集合的方式有:迭代器、forEach、for、sort其中foreach和sort需要的对象都是一个接口 我们通过匿名内部类的方式new 对象。代码很繁琐


        ArrayList<Integer> list = new ArrayList<>();
        list.add(45);
        list.add(12);
        list.add(32);
        list.add(78);
        list.add(56);
        list.add(3);
       System.out.println("列表迭代器遍历");
        ListIterator<Integer> iterator = list.listIterator();
        while (iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println(next);
        }
       System.out.println("迭代器遍历");
       Iterator<Integer> it = list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
      
	    System.out.println("forEach遍历");
        list.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        });
	
	  System.out.println("for循环遍历");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

		  System.out.println("sort方式遍历");
         Comparator<Integer> comparator = new Comparator<Integer>(){
            @Override
            public int compare(Integer a, Integer b) {
                return a - b;
            }
         };
        list.sort(comparator);
        System.out.println(list)

forEach、sort方法都需要的是一个接口,下面通过具体的实现推导Lambda表达式语法:

Lambda表达式语法
左边右边
方法名里面的参数列表方法体内的逻辑
        //使用Lambda表达式
 
        Comparator<Integer> comparator2 = (Integer a,Integer b)->{
            return a - b;
        };
        list.sort(comparator2);
        System.out.println("comparator2的排序:"+list);

        Comparator<Integer> comparator3 = (a,b)->a-b;
        list.sort(comparator3);
        System.out.println("comparator3的排序:"+list);


        System.out.println("===============");
        list.sort((a,b)->a-b);
        System.out.println(list);

遍历集合也没有真实的感受到为什么实用Lambda表达式它的好处有哪些
如果我现在定义了一个交易员和交易类,代码如下

public class Trader {
    private String name;  //交易员的姓名
    private String city;    //交易员工作的城市

    public Trader(String name, String city) {
        this.name = name;
        this.city = city;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Trader{" +
                "name='" + name + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

public class Transaction {
    private Trader trader; //交易员
    private int year;  //年份
    private int value; //交易额

    public Transaction(Trader trader, int year, int value) {
        this.trader = trader;
        this.year = year;
        this.value = value;
    }

    public Trader getTrader() {
        return trader;
    }

    public void setTrader(Trader trader) {
        this.trader = trader;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Transaction{" +
                "trader=" + trader +
                ", year=" + year +
                ", value=" + value +
                '}';
    }
}

添加数据!

  Trader raoul = new Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario", "Milan");
        Trader alan = new Trader("Alan", "Cambridge");
        Trader brian = new Trader("Brian", "Cambridge");

        List<Transaction> ts = Arrays.asList(
              new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2011, 1000),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(raoul, 2011, 1200),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );

需求:找出2011年发生的所有交易,并按交易额排序(从低到高)
使用匿名内部类

     ts.sort(new Comparator<Transaction>() {
                @Override
                public int compare(Transaction o1, Transaction o2) {
                    return 0;
                }
            });
            System.out.println("=========");
            Stream<Transaction> s1 = ts.stream().filter(new Predicate<Transaction>() {
                @Override
                public boolean test(Transaction transaction) {
                    return transaction.getYear() == 2011;
                }
            });
            Stream<Transaction> sorted = s1.sorted(new Comparator<Transaction>() {
                @Override
                public int compare(Transaction a, Transaction b) {
                    return a.getValue() - b.getValue();
                }
            });
            sorted.forEach(new Consumer<Transaction>() {
                @Override
                public void accept(Transaction transaction) {
                    System.out.println(transaction);
                }
            });

如果使用Lambda表达式只需要链式编程,代码很简便

  ts.stream().filter(transaction -> transaction.getYear() == 2011)
  .sorted(Comparator.comparing(Transaction::getValue))
  .forEach(System.out::println);

怎么样Lambda表达式是不是很好用!

2.函数式接口

函数式接口上都有@FunctionalInterface注解
函数式接口:就是接口只包含一个抽象方法
常用的4大核心函数式接口

  • 消费型接口 Consumer<T>
  • 方法:void accept(T t); 有参 无返回值
   new Consumer<User>(){
           @Override
           public void accept(User user) {
               System.out.println(user.toString());
           }
       };
  • 函数型接口 Function<T, R>
  • 方法: R apply(T t); 有参且有返回值 T代表是输入类型 R返回结果类型

       new Function<User,String>(){
           @Override
           public String apply(User user) {
               return user.getName();
           }
       };
  • 断言新接口 Predicate<T>
  • 方法: boolean test(T t); 代表输入类型 有参返回值是boolean值
       new Predicate<User>(){
           @Override
           public boolean test(User user) {
               return user.getName().equals("李四");
           }
       }; 
  • 供给型接口 Supplier<T>
  • 方法:T get(); 无参且返回类型T的对象
     new Supplier<Integer>(){
         @Override
         public Integer get() {
             return 2;
         }
     };
2.1方法引用

1.类::实例方法

如果参数列表和返回值类型一致
* void accept(T t);
* PrintStream out = System.out;
* out.println(a);
* accept 不需要返回值 println方法也不需要返回值 且需要的参数一致所以可以使用 类::实例方法

        //匿名内部类的方式:
        Consumer<Integer> co = new Consumer<Integer>() {
            @Override
            public void accept(Integer a) {
                System.out.println(a);
                PrintStream out = System.out;
                out.println(a);
            }
        };

        //Lambda表达式
        Consumer<Integer> co2 = a -> System.out.println(a);
        co2.accept(2);

        //方法应用: 类::实例方法
        Consumer<Integer> co3 = System.out::println;

2.类::静态方法

  • R apply(T t, U u);
    * public static double max(double a, double b)
    * 方法引用:类::静态方法
    * 如何判断什么时候使用该方式
    * 如果参数列表和返回值类型一致就使用方法引用
        //匿名内部类
        BinaryOperator<Double> b2 = new BinaryOperator<Double>() {
            @Override
            public Double apply(Double d1, Double d2) {
                return Math.max(d1, d2);
            }
        };
        System.out.println(b2.apply(10.0, 12.0));

        //Lambda表达式
        BinaryOperator<Double> b3 = (a, b) -> Math.max(a, b);
        System.out.println(b3.apply(15.2, 15.3));
        //方法引用 类::静态方法
        BinaryOperator<Double> b4 = Math::max;
        System.out.println(b4.apply(15.2, 15.3));

3.对象::实例方法

*如何判断什么时候使用 对象::实例方法
* 当我们看见方法应用中第一个参数是调用者,第二个参数是被调用者,且两个参数均来自compare方法的参数列表中

        //匿名内部类的方式
        Comparator<Integer> c1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return a.compareTo(b);
            }
        };
        System.out.println(c1.compare(20, 10));

        //Lambda表达式
        Comparator<Integer> c2 = (a, b) -> a.compareTo(b);

        //方法引用
        Comparator<Integer> c3 = Integer::compareTo;

        System.out.println("======下面是构造器引用的实例=======");
2.2构造引用

类名::new

  • return 返回的是一个对象 对象的无参构造与get方法参数列表一致
        //匿名内部类
        Supplier<User> s1 = new Supplier<User>() {
            @Override
            public User get() {
                return new User(12, "张三");
            }
        };

        //Lambda表达式
        Supplier<User> s2 = () -> new User(12, "张三);
        System.out.println(s2.get().toString());

        //构造器引用
        Supplier<User> s3 = User::new;
        System.out.println(s3.get().toString());

3.Stream流

Stream流步骤:
1.创建Stream
2.中间操作
3.终止操作

3.0创建Stream的五种方式:

1.集合的方式创建stream流

  //1.集合的方式创建stream流
        List<String> list = new ArrayList<>();
        Stream<String> s1 = list.stream();

2数组创建stream流.

        //2.数组创建stream流
        int[] arr = {10,30,5,2};
        IntStream s2 = Arrays.stream(arr);

3.Stream.generate创建无限流

        //3.无限流
        Stream<Double> generate = Stream.generate(() -> {
            return Math.random()*10;//获取double类型10以内的随机数
        });
        Stream<Double> limit = generate.limit(5);
        limit.forEach(System.out::println);

4.Stream.iterate创建无限流

        //4.无限流
        //从零开始步长是1的十个元素
        Stream<Integer> stream = Stream.iterate(0, a -> a + 1);
        Stream<Integer> limit1 = stream.limit(10);
        limit1.forEach(System.out::println);

5.Stream的静态方法of()

        //5.Stream的静态方法of()
        Stream<List<String>> newStream = Stream.of(list);
        Stream<int[]> newStream2 = Stream.of(arr);

准备实体类:

public class Supplyer {
    private int  year;//产品的创建时间
    private String city;//产品的发源地
    //get、set方法省略
}
public class Products {
    private String name;//产品的名字
    private Supplyer supplyer;//供应商
    private int ranking;//产品的排名
    private Double price;//产品的价格
    //get、set方法省略
}

创建信息类:添加数据

public class ProductsService {
   public static List<Products> getList(){
       Supplyer HeadShoulders = new Supplyer(1993, "广东");//海飞丝
       Supplyer Sassoon = new Supplyer(2001, "英国");//沙宣
       Supplyer clear = new Supplyer(1994, "上海");//清扬
       Supplyer Schwarzkopf = new Supplyer(1995, "上海");//施华蔻
       Supplyer lux = new Supplyer(1994, "上海");//Lux


       List<Products> userList = new ArrayList<>();
       userList.add(new Products("海飞丝", HeadShoulders, 10,35.90));
       userList.add(new Products("沙宣", Sassoon, 6,25.5));
       userList.add(new Products("清扬", clear, 2,36.0));
       userList.add(new Products("施华蔻", Schwarzkopf, 10,45.5));
       userList.add(new Products("Lux", lux, 4,9.9));
       return userList;
   }
 }
3.1查询
3.11forEach

使用forEach遍历所有元素

 List<Products> list = ProductsService.getList(); List<Products> list = ProductsService.getList();
 //遍历所有产品的信息
 //list.stream().forEach(System.out::println);
 list.stream().forEach(Products-> System.out.println(Products));//等价于上面的查询语句

执行结果:

Products{品牌=‘海飞丝’, supplyer=Supplyer{创建时间=1993, 城市=‘广东’}, 排名=10, price=35.9}
Products{品牌=‘沙宣’, supplyer=Supplyer{创建时间=2001, 城市=‘英国’}, 排名=6, price=25.5}
Products{品牌=‘清扬’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=2, price=36.0}
Products{品牌=‘施华蔻’, supplyer=Supplyer{创建时间=1995, 城市=‘上海’}, 排名=10, price=45.5}
Products{品牌=‘Lux’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=4, price=9.9}

3.12filter

使用filter过滤列表数据

      //查询产地是上海的品牌
        Stream<Products> stream2 = list.stream();
        Stream<Products> productsStream = stream2.filter(Products -> Products.getSupplyer().getCity().equals("上海"));
        productsStream.forEach(System.out::println);

执行结果:

Products{品牌=‘清扬’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=2, price=36.0}
Products{品牌=‘施华蔻’, supplyer=Supplyer{创建时间=1995, 城市=‘上海’}, 排名=10, price=45.5}
Products{品牌=‘Lux’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=4, price=9.9}

3.13findFirst()

使用findFirst()第一条数据

   Stream<Products> stream3 = list.stream();
        Products products = stream3.filter(Products -> Products.getName().equals("沙宣")).findFirst().orElse(null);
        System.out.println(products);

执行结果:

Products{品牌=‘沙宣’, supplyer=Supplyer{创建时间=2001, 城市=‘英国’}, 排名=6, price=25.5}

3.14map 、flatMap

使用 map() 将流中的每一个元素 T 映射为 R
使用 flatMap() 将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流。

 //获取1994时间的supply
        List<Supplyer> collect = list.stream().map(Products::getSupplyer).filter(Products -> Products.getYear() == 1994).collect(Collectors.toList());
        collect.forEach(System.out::println);

执行结果:

Supplyer{创建时间=1994, 城市=‘上海’}
Supplyer{创建时间=1994, 城市=‘上海’}

//分隔城市每一个元素为一个流
 List<String> cityList = new ArrayList<>();
        cityList.add("北京;上海;深圳;");
        cityList.add("广州;武汉;杭州;");
        cityList.stream().map(s -> s.split(";")).flatMap(Arrays::stream).collect(Collectors.toList()).forEach(System.out::println);

执行结果:

北京
上海
深圳
广州
武汉
杭州

3.15limit、skip

limit(long n) 方法用于返回前n条数据,skip(long n) 方法用于跳过前n条数据。

        //limit 筛选价格大于30 
        Stream<Products> limit = list.stream().filter(Products -> Products.getPrice() > 30).limit(3);
        limit.forEach(System.out::println);
        System.out.println("skip");

执行结果:

Products{品牌=‘海飞丝’, supplyer=Supplyer{创建时间=1993, 城市=‘广东’}, 排名=10, price=35.9}
Products{品牌=‘清扬’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=2, price=36.0}
Products{品牌=‘施华蔻’, supplyer=Supplyer{创建时间=1995, 城市=‘上海’}, 排名=10, price=45.5}

      //skip 筛选的结果跳过前两个
        Stream<Products> skip = list.stream().filter(Products -> Products.getPrice() > 30).skip(2);
        skip.forEach(System.out::println);

执行结果:

Products{品牌=‘施华蔻’, supplyer=Supplyer{创建时间=1995, 城市=‘上海’}, 排名=10, price=45.5}

3.16distinct

使用distinct可以去除重复元素

    Stream<String> distinct = list.stream().map(Products -> Products.getSupplyer().getCity()).distinct();
        distinct.forEach(System.out::println);

执行结果

广东
英国
上海

3.2判断方法

使用 anyMatch(T -> boolean) 判断流中是否有一个元素匹配给定的 T -> boolean 条件。
使用 allMatch(T -> boolean) 判断流中是否所有元素都匹配给定的 T -> boolean 条件。
使用 noneMatch(T -> boolean) 流中是否没有元素匹配给定的 T -> boolean 条件。

 
        //判断用户列表是否存在上海的数据
        boolean anyMatch = list.stream().anyMatch(Products -> Products.getSupplyer().getCity().equals("上海"));//true
        System.out.println(anyMatch);
        //判断用户列表是否包含潘婷的品牌
        boolean allMatch = list.stream().allMatch(Products -> Products.getName().contains("潘婷"));
        System.out.println(allMatch);//false
        //判断用户列表中是否存在价格小于10的产品
        boolean noneMatch = list.stream().noneMatch(Products -> Products.getPrice() < 10);
        System.out.println(noneMatch);//false

执行结果:

true
false
false

3.3统计方法

使用 reduce((T, T) -> T) 和 reduce(T, (T, T) -> T) 用于组合流中的元素,如求和,求积,求最大值等。
使用 counting() 和 count() 可以对列表数据进行统计。

        Double max = list.stream().map(Products::getPrice).reduce(Double::max).get();
        Double min = list.stream().map(Products::getPrice).reduce(Double::min).get();
        System.out.println("价格最贵:"+max);
        System.out.println("价格最便宜:"+min);
        //统计在列表中排名第一的品牌
        list.stream().filter(Products->Products.getRanking() <= 2).forEach(System.out::println);

执行结果:

价格最贵:45.5
价格最便宜:9.9
Products{品牌=‘清扬’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=2, price=36.0}

   Long aLong = list.stream().filter(Products -> Products.getSupplyer().getCity().equals("上海")).collect(Collectors.counting());
        System.out.println("上海的品牌有"+aLong+"家");
        long cout = list.stream().filter(Products -> Products.getSupplyer().getYear() > 1990).count();
        System.out.println("产品的创建时间大于1990的品牌有"+cout+"家");

执行结果:

上海的品牌有3家
产品的创建时间大于1990的品牌有5家

3.4排序方法

如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序,如 Stream。反之, 需要调用 sorted((T, T) -> int) 实现 Comparator 接口。


        //升序
        list.stream().sorted((p1,p2)->p1.getRanking() - p2.getRanking()).collect(Collectors.toList()).forEach(System.out::println);

        //升序   推荐下面这两种排序方法
        List<Products> co = list.stream().sorted(Comparator.comparingInt(Products::getRanking)).collect(Collectors.toList());
        co.forEach(System.out::println);
        //降序
        List<Products> co2 = list.stream().sorted(Comparator.comparingInt(Products::getRanking).reversed()).collect(Collectors.toList());
        co2.forEach(System.out::println);


执行结果:

Products{品牌=‘清扬’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=2, price=36.0}
Products{品牌=‘Lux’, supplyer=Supplyer{创建时间=1994, 城市=‘上海’}, 排名=4, price=9.9}
Products{品牌=‘沙宣’, supplyer=Supplyer{创建时间=2001, 城市=‘英国’}, 排名=6, price=25.5}
Products{品牌=‘海飞丝’, supplyer=Supplyer{创建时间=1993, 城市=‘广东’}, 排名=10, price=35.9}
Products{品牌=‘施华蔻’, supplyer=Supplyer{创建时间=1995, 城市=‘上海’}, 排名=10, price=45.5}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值