Java8新特性

Stream流

Stream 是JDK1.8 中处理集合的关键抽象概念,Lambda 和 Stream 是JDK1.8新增的函数式编程最有亮点的特性了,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由**最终操作(terminal operation)**得到前面处理的结果。

Stream :非常方便精简的形式遍历集合实现 过滤、排序等。

Stream创建方式

public class Test01 {
    public static void main(String[] args) {
        ArrayList<UserEntity> userEntities = new ArrayList<>();
        userEntities.add(new UserEntity("mayikt", 20));
        userEntities.add(new UserEntity("meite", 28));
        userEntities.add(new UserEntity("zhangsan", 35));
        /**
         * user 对象属性值都是相等的 但是new 两个对象 这两个对象的 内存地址 是不一样的
         */
        userEntities.add(new UserEntity("xiaowei", 16));
        userEntities.add(new UserEntity("xiaowei", 16));
        userEntities.forEach((t) -> {
            System.out.println(t.toString());
        });
        System.out.println("重写UserEntity的equal方法后,将list集合通过stream转换为set集合后会自动去除重复...");
        /**
         * 创建stream方式两种
         * 1.串行流stream() 单线程
         * 2.并行流parallelStream() 多线程
         * 并行流parallelStream 比串行流stream()效率要高的
         */
        Stream<UserEntity> stream = userEntities.stream();
        // 转换成set集合
        Set<UserEntity> setUserList = stream.collect(Collectors.toSet());
        setUserList.forEach(userEntity -> {
            System.out.println(userEntity.toString());
        });
    }
}


 class UserEntity {
    private String userName;
    private int age;
    public UserEntity() {
    }
    public UserEntity(String userName, int age) {
        this.userName = userName;
        this.age = age;
    }
    public String getUserName() {
        return userName;
    }
    public int getAge() {
        return age;
    }
    @Override
    public String toString() {
        return "UserEntity{" +
                "userName='" + userName + '\'' +
                ", age=" + age +
                '}';
    }
    //    @Override
    public int hashCode() {
        return userName.hashCode();
    }
    public boolean equals(Object obj) {
        if (obj instanceof UserEntity)
            return userName.equals(((UserEntity) obj).userName) && age == (((UserEntity) obj).age);
        else
            return false;
    }
}

—————————-将list集合转换为map————————–

public class Test02 {
    public static void main(String[] args) {
        ArrayList<UserEntity> userEntities = new ArrayList<>();
        userEntities.add(new UserEntity("mayikt", 20));
        userEntities.add(new UserEntity("meite", 28));
        userEntities.add(new UserEntity("zhangsan", 35));
        // list集合只有元素值 key list转换成map集合的情况下 指定key--user对象 username属性  value user对象
        /**
         * map<String(userName),UserEntity>
         */
        Stream<UserEntity> stream = userEntities.stream();
        /**
         * new Function<UserEntity(list集合中的类型), String(key map)>
         */
        Map<String, UserEntity> collect = stream.collect(Collectors.toMap(userEntity -> userEntity.getUserName(), userEntity -> userEntity));
        collect.forEach((BiConsumer) (o, o2) -> System.out.println(o + "," + o2));
    }
}

使用java.util.Arrays.stream(T[] array)方法用数组创建流

int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);

使用Stream的静态方法:of()、iterate()、generate()

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println); // 0 2 4 6 8 10

Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);

Stream API

forEach

Stream 提供了新的方法 ‘forEach’ 来迭代流中的每个数据。

public class TestTTTT {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
         strings.stream().filter(s -> !s.isEmpty()).forEach(System.out::println);
    }
}

结果:
abc
bc
efg
abcd
jkl

Process finished with exit code 0

map

接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
 System.out.println(squaresList);

结果: 
[9, 4, 49, 25]
    
  ArrayList<UserEntity> userEntities = new ArrayList<>();
   userEntities.add(new UserEntity("mayikt", 20));
   userEntities.add(new UserEntity("meite", 28));
   userEntities.add(new UserEntity("zhangsan", 35));
   userEntities.add(new UserEntity("xiaowei", 16));
   userEntities.add(new UserEntity("xiaowei", 16));
   List<String> list=null;
   list= userEntities.stream().map(u -> u.getUserName()).collect(Collectors.toList());
   System.out.println(list);

结果:
[mayikt, meite, zhangsan, xiaowei, xiaowei]    

flatMap

接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

案例:将两个字符数组合并成一个新的字符数组。

class StreamTest {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("m-k-l-a", "1-3-5-7");
        List<String> listNew = list.stream().flatMap(s -> {
            // 将每个元素转换成一个stream
            String[] split = s.split("-");
            Stream<String> s2 = Arrays.stream(split);
            return s2;
        }).collect(Collectors.toList());

        System.out.println("处理前的集合:" + list);
        System.out.println("处理后的集合:" + listNew);
    }
}

结果:
    
处理前的集合:[m-k-l-a, 1-3-5-7]
处理后的集合:[m, k, l, a, 1, 3, 5, 7]

Process finished with exit code 0

filter

filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();
System.out.println(count);

结果:
    2
public class Test14 {
    public static void main(String[] args) {
        ArrayList<UserEntity> userEntities = new ArrayList<>();
        userEntities.add(new UserEntity("mayikt", 20));
        userEntities.add(new UserEntity("wangmazi", 19));
        userEntities.add(new UserEntity("xiaoke", 19));
        userEntities.add(new UserEntity("xiaoan", 21));
        userEntities.add(new UserEntity("mayikt", 12));
        // where userName='mayikt' and age>18
        Stream<UserEntity> stream = userEntities.stream();
        stream.filter(userEntity -> "mayikt".equals(userEntity.getUserName()) && userEntity.getAge() > 18)
                .forEach((userEntity -> System.out.println(userEntity)));
    }
}


结果:
UserEntity{userName='mayikt', age=20}

Process finished with exit code 0
   

limit

limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 3 条数据:

 List<String>str1 = Arrays.asList("abc", "bc", "efg", "abcd", "jkl");
 str1.stream().limit(3).forEach(System.out::println);

结果:
abc
bc
efg

sorted

sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

案例:

public class StreamTest {
 public static void main(String[] args) {
  List<Person> personList = new ArrayList<Person>();

  personList.add(new Person("Sherry", 9000, 24, "female", "New York"));
  personList.add(new Person("Tom", 8900, 22, "male", "Washington"));
  personList.add(new Person("Jack", 9000, 25, "male", "Washington"));
  personList.add(new Person("Lily", 8800, 26, "male", "New York"));
  personList.add(new Person("Alisa", 9000, 26, "female", "New York"));

  // 按工资增序排序
  List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
    .collect(Collectors.toList());
  // 按工资倒序排序
  List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
    .map(Person::getName).collect(Collectors.toList());
  // 先按工资再按年龄自然排序(从小到大)
  List<String> newList3 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
    .map(Person::getName).collect(Collectors.toList());
  // 先按工资再按年龄自定义排序(从大到小)
  List<String> newList4 = personList.stream().sorted((p1, p2) -> {
   if (p1.getSalary() == p2.getSalary()) {
    return p2.getAge() - p1.getAge();
   } else {
    return p2.getSalary() - p1.getSalary();
   }
  }).map(Person::getName).collect(Collectors.toList());

  System.out.println("按工资自然排序:" + newList);
  System.out.println("按工资降序排序:" + newList2);
  System.out.println("先按工资再按年龄自然排序:" + newList3);
  System.out.println("先按工资再按年龄自定义降序排序:" + newList4);
 }
}

结果:
按工资自然排序:[Lily, Tom, Sherry, Jack, Alisa]
按工资降序排序:[Sherry, Jack, Alisa,Tom, Lily]
先按工资再按年龄自然排序:[Sherry, Jack, Alisa, Tom, Lily]
先按工资再按年龄自定义降序排序:[Alisa, Jack, Sherry, Tom, Lily]        

Collectors

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
System.out.println("打印列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining("+"));
System.out.println("合并字符串: " + mergedString);

结果:
打印列表: [abc, bc, efg, abcd, jkl]
合并字符串: abc+bc+efg+abcd+jkl

统计1

  List<Integer> num = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        IntSummaryStatistics stats = num.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("列表中最大的数 : " + stats.getMax());
        System.out.println("列表中最小的数 : " + stats.getMin());
        System.out.println("所有数之和 : " + stats.getSum());
        System.out.println("平均数 : " + stats.getAverage());

結果:
    
列表中最大的数 : 7
列表中最小的数 : 2
所有数之和 : 25
平均数 : 3.5714285714285716
    
  List<Double> num = Arrays.asList(3.00, 2.00, 2.00, 3.00, 7.00, 3.00, 5.00);
  DoubleSummaryStatistics stats = num.stream().mapToDouble((x) -> x).summaryStatistics();
        System.out.println("列表中最大的数 : " + stats.getMax());
        System.out.println("列表中最小的数 : " + stats.getMin());
        System.out.println("所有数之和 : " + stats.getSum());
        System.out.println("平均数 : " + stats.getAverage());

結果:
    
列表中最大的数 : 7.0
列表中最小的数 : 2.0
所有数之和 : 25.0
平均数 : 3.5714285714285716
public class Test11 {
    public static void main(String[] args) {
        Stream<Integer> integerStream = Stream.of(10, 50, 30, 10);
        Optional<Integer> reduce = integerStream.reduce(new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer a1, Integer a2) {
                return a1 + a2;
            }
        });
        System.out.println(reduce.get());

        ArrayList<UserEntity> userEntities = new ArrayList<>();
        userEntities.add(new UserEntity("mayikt", 20));
        userEntities.add(new UserEntity("meite", 28));
        userEntities.add(new UserEntity("zhangsan", 35));
        userEntities.add(new UserEntity("liusi", 21));
        userEntities.add(new UserEntity("wangmazi", 19));
        userEntities.add(new UserEntity("xiaoke", 19));
        userEntities.add(new UserEntity("xiaoan", 21));
        Stream<UserEntity> stream = userEntities.stream();
        Optional<UserEntity> sum = stream.reduce((user1, user2) -> {
            UserEntity userEntity = new UserEntity("sum", user1.getAge() + user2.getAge());
            return userEntity;
        });
        System.out.println(sum.get());
        System.out.println(sum.get().getAge());
    }
}

结果:
100
UserEntity{userName='sum', age=163}
163

Process finished with exit code 0
public class Test12 {
    public static void main(String[] args) {

        ArrayList<UserEntity> userEntities = new ArrayList<>();
        userEntities.add(new UserEntity("mayikt", 20));
        userEntities.add(new UserEntity("meite", 28));
        userEntities.add(new UserEntity("zhangsan", 35));
        userEntities.add(new UserEntity("liusi", 21));
        userEntities.add(new UserEntity("wangmazi", 19));
        userEntities.add(new UserEntity("xiaoke", 19));
        userEntities.add(new UserEntity("xiaoan", 21));
        Stream<UserEntity> stream = userEntities.stream();
        Optional<UserEntity> min = stream.min((o1, o2) -> o1.getAge() - o2.getAge());
        System.out.println(min.get());
    }
}

结果:
  
UserEntity{userName='wangmazi', age=19}

Process finished with exit code 0

统计2

Collectors提供了一系列用于数据统计的静态方法:

  • 计数:count
  • 平均值:averagingIntaveragingLongaveragingDouble
  • 最值:maxByminBy
  • 求和:summingIntsummingLongsummingDouble
  • 统计以上所有:summarizingIntsummarizingLongsummarizingDouble
class StreamTest {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));

        // 求总数
        Long count = personList.stream().collect(Collectors.counting());
        // 求平均工资
        Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
        // 求最高工资
        Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
        // 求最低工资
        Optional<Integer> min = personList.stream().map(Person::getSalary).collect(Collectors.minBy(Integer::compare));
        // 求工资之和
          Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
        //Integer sum = personList.stream().map(e->e.getSalary()).collect(Collectors.summingInt(e->e));
        // 一次性统计所有信息
        DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

        System.out.println("员工总数:" + count);
        System.out.println("员工平均工资:" + average);
        System.out.println("员工最高工资:" + max.get());
        System.out.println("员工最低工资:" + min.get());
        System.out.println("员工工资总和:" + sum);
        System.out.println("员工工资所有统计:" + collect);
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Person{
    private String name;
    private Integer salary;
    private Integer age;
    private String sex;
    private String  city;
}
结果:
员工总数:3
员工平均工资:7900.0
员工最高工资:8900
员工最低工资:7000
员工工资总和:23700
员工工资所有统计:DoubleSummaryStatistics{count=3, sum=23700.000000, min=7000.000000, average=7900.000000, max=8900.000000}

Process finished with exit code 0

Match

  • anyMatch表示,判断的条件里,任意一个元素成功,返回true
  • allMatch表示,判断条件里的元素,所有的都是,返回true
  • noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
public class Test13 {
    public static void main(String[] args) {
        ArrayList<UserEntity> userEntities = new ArrayList<>();
        userEntities.add(new UserEntity("mayikt", 20));
        userEntities.add(new UserEntity("meite", 28));
        userEntities.add(new UserEntity("zhangsan", 35));
        Stream<UserEntity> stream = userEntities.stream();
        boolean b = stream.allMatch(userEntity -> "mayikt".equals(userEntity.getUserName()));
        System.out.println(b);
    }
}

结果:

false

Process finished with exit code 0

聚合(max/min/count)

案例一:获取String集合中最长的元素。

public class StreamTest {
 public static void main(String[] args) {
  List<String> list = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");

  Optional<String> max = list.stream().max(Comparator.comparing(String::length));
  System.out.println("最长的字符串:" + max.get());
 }
}

结果:
最长的字符串:weoujgsd

案例二:获取Integer集合中的最大值

public class Stream {

            public static void main(String[] args) {
                List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);

                // 自然排序
                Optional<Integer> max = list.stream().max(Integer::compareTo);
                // 1自定义排序
                Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        return o1.compareTo(o2);
                    }
                });
                // 2自定义排序
                Optional<Integer> max3 = list.stream().max((e1,e2)->e1.compareTo(e2));
                System.out.println("自然排序的最大值:" + max.get());
                System.out.println("1自定义排序的最大值:" + max2.get());
                System.out.println("2自定义排序的最大值:" + max3.get());
            }
        }


自然排序的最大值:11
1自定义排序的最大值:11
2自定义排序的最大值:11

Process finished with exit code 0

案例三:获取员工工资最高的人。

public class StreamTest {
 public static void main(String[] args) {
  List<Person> personList = new ArrayList<Person>();
  personList.add(new Person("Tom", 8900, 23, "male", "New York"));
  personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
  personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
  personList.add(new Person("Anni", 8200, 24, "female", "New York"));
  personList.add(new Person("Owen", 9500, 25, "male", "New York"));
  personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

  Optional<Person> max = personList.stream().max(Comparator.comparingInt(Person::getSalary));
  System.out.println("员工工资最大值:" + max.get().getSalary());
 }
}


员工工资最大值:9500

案例四:计算Integer集合中大于6的元素的个数。

import java.util.Arrays;
import java.util.List;

public class StreamTest {
 public static void main(String[] args) {
  List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);

  long count = list.stream().filter(x -> x > 6).count();
  System.out.println("list中大于6的元素个数:" + count);
 }
}


list中大于6的元素个数:4

joining

joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。

public class StreamTest {
 public static void main(String[] args) {
  List<Person> personList = new ArrayList<Person>();
  personList.add(new Person("Tom", 8900, 23, "male", "New York"));
  personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
  personList.add(new Person("Lily", 7800, 21, "female", "Washington"));

  String names = personList.stream().map(p -> p.getName()).collect(Collectors.joining(","));
  System.out.println("所有员工的姓名:" + names);
  List<String> list = Arrays.asList("A", "B", "C");
  String string = list.stream().collect(Collectors.joining("-"));
  System.out.println("拼接后的字符串:" + string);
 }
}


结果:
    
所有员工的姓名:Tom,Jack,Lily
拼接后的字符串:A-B-C

Lambda表达式

Java8中的接口

在jdk8之前,interface之中可以定义变量和方法,变量必须是public、static、final的,方法必须是public、abstract的,这些修饰符都是默认的。

接口定义方法:public 抽象方法 需要子类实现

接口定义变量:public、static、final

在JDK 1.8开始 支持使用static和default 修饰 可以写方法体,不需要子类重写。

方法:

普通方法:可以有方法体

抽象方法 :没有方法体需要子类实现 重写。

public interface JDK8Interface {
    //抽象方法
    void addOrder();
    //默认方法 可以写方法体
    default void getDefaultOrder() {
        System.out.println("我是默认方法 我可以写方法体");
    }
    //静态方法 可以写方法体
    static void getStaticOrder() {
        System.out.println("我是静态的方法 可以写方法体");
    }
}
public class JDK8InterfaceImpl implements JDK8Interface {
    /**
     * 默认和静态方法不是我们的抽象方法 ,所以不需要重写
     */
    @Override
    public void addOrder() {
        System.out.println("addOrder");
    }
}

Lambda表达式

先定义一个接口:

public interface OrderService {
    void get();
    /**
     * 如果需要使用到OrderService接口
     * 接口是无法new、可以通过匿名内部类new
     * 定义子类
     */
}

调用接口:

public class Test02 {
    public static void main(String[] args) {
        // 1.使用new的实现类的形式调用接口
    OrderService orderSerivce1 = new OrderSerivceImpl();
    orderSerivce1.get();
        //2.使用匿名内部类的形式调用OrderService 中get方法
       OrderService orderService = new OrderService() {
           //--------------这个注解也可以不写-------------------
           @Override
           public void get() {
               System.out.println("get");
           }
      };
       orderService.get();
        //或者直接:
        new OrderService() {
           @Override
           public void get() {
               System.out.println("get");
           }
      }.get();
        //3.使用lambda调用接口
        
        OrderService orderService= () -> {
            System.out.println("get")
        };
        orderService.get();
        //简化:
        ((OrderService) () -> System.out.println("get")).get();
        //4.创建一个线程
         new Thread(() -> System.out.println(Thread.currentThread().getName() + ",run")).start();
    }
}

Lambda表达式的规范

使用Lambda表达式 依赖于函数接口

  1. 在接口中只能够允许有一个抽象方法

  2. 在函数接口中定义object类中方法 (在函数接口中可以有继承于object类的方法 )

  3. 使用默认或者静态方法

  4. @FunctionalInterface 表示该接口为函数接口

Java中的Lambda表达式的规范,必须是为函数接口。

函数接口的定义:在该接口中只能存在一个抽象方法,该接口称作为函数接口

JDK中自带的函数接口:

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.security.PrivilegedAction
  • java.util.Comparator
  • java.io.FileFilter
  • java.nio.file.PathMatcher
  • java.lang.reflect.InvocationHandler
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener

我们也可以使用@FunctionalInterface修饰为函数接口

函数接口的定义

  1. 在接口中只能有一个抽象方法

  2. @FunctionalInterface 标记为该接口为函数接口

  3. 可以通过default 修饰为普通方法

  4. 可以定义object类中的方法

@FunctionalInterface
public interface MyFunctionalInterface {
    void get();
    default void defaultAdd() {
        System.out.println("我是默认的方法");
    }
    /**
     * object父类中的方法可以在函数接口中重写
     */
    String toString();
}

可以理解为lambda就是重写实现了函数接口中的抽象方法,从而快速直接通过接口调用方法

Lambda表达式的语法

无参方法调用

public interface AcanthopanaxInterface {
    void get();
}

AcanthopanaxInterface acanthopanaxInterface = () -> {
    System.out.println("使用lamdba表达式调用方法");
};
acanthopanaxInterface.get();

带参数和返回值

@FunctionalInterface
public interface YouShenInterface {
    String get(int i, int j);
}

public class Test04 {
    public static void main(String[] args) {
        // 1.使用匿名内部类调用有参数函数方法
//        String result = new YouShenInterface() {
//            @Override
//            public String get(int i, int j) {
//                return i + "-" + j;
//            }
//        }.get(1, 1);
//        System.out.println(result);
        //2.使用lamdba 调用有参数函数方法,不用写参数类型
        YouShenInterface youShenInterface = (i, j) -> {
            System.out.println("mayikt:" + i + "," + j);
            return i + "-" + j;
        };
        System.out.println(youShenInterface.get(1, 1));
    }
}

精简语法

//        1.精简写法优化 如果方法体中只有一条语句的情况下 可以不需要写{}
//        AcanthopanaxInterface acanthopanaxInterface = () -> {
//            System.out.println("mayikt");
//        };
//        acanthopanaxInterface.get();

        AcanthopanaxInterface acanthopanaxInterface2 = () ->
                System.out.println("mayikt");
        acanthopanaxInterface2.get();
        ;
//        2.如果方法体只有一条return的情况下不需要些{} 和return
//        YouShenInterface youShenInterface = (i, j) -> {
//            return i + "-" + j;
//        };
//       优化后
        YouShenInterface youShenInterface2 = (i, j) -> i + "-" + j;
        System.out.println(youShenInterface2.get(1, 2));
      //((YouShenInterface)(i,j)-> i + "--" + j).get(1,2);

Lambda实例

遍历集合

Foreach:

 ArrayList<String> strings = new ArrayList<>();
        strings.add("mayikt");
        strings.add("xiaowei");
        strings.add("xiaomin");
//        strings.forEach(new Consumer() {     
//----------------函数接口:Consumer()
//            @Override
//            public void accept(Object o) {
//                System.out.println("o:" + o);
//            }
//        });
        strings.forEach((o) -> {
            System.out.println(o);
        });

集合排序

public class UserEntity {
    private String name;
    private Integer age;
    public UserEntity(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public Integer getAge() {
        return age;
    }
        ArrayList<UserEntity> userlists = new ArrayList<>();
        userlists.add(new UserEntity("mayikt", 22));
        userlists.add(new UserEntity("xiaomin", 18));
        userlists.add(new UserEntity("xiaoha", 36));
//        userlists.sort(new Comparator<UserEntity>() {   
//---------------Comparator<UserEntity>()是一个函数接口
//            @Override
//            public int compare(UserEntity o1, UserEntity o2) {
//                return o1.getAge() - o2.getAge();
//            }
//        });
        userlists.sort((o1, o2) ->
                o1.getAge() - o2.getAge()
        );
        userlists.forEach((Consumer) o -> System.out.println("o:" + o.toString()));
    
    
  结果:通过年龄排序
UserEntity{userName='xiaoxiao', age=6}
UserEntity{userName='xiaomin', age=12}
UserEntity{userName='xiaojun', age=23}

Process finished with exit code 0    
      

List转换为Map

public class Test02 {
    public static void main(String[] args) {
        ArrayList<UserEntity> userEntities = new ArrayList<>();
        userEntities.add(new UserEntity("mayikt", 20));
        userEntities.add(new UserEntity("meite", 28));
        userEntities.add(new UserEntity("zhangsan", 35));


        // list集合只有元素值 key list转换成map集合的情况下 指定key--user对象 username属性  value user对象
        /**
         * map<String(userName),UserEntity>
         */
        Stream<UserEntity> stream = userEntities.stream();
        /**
         * new Function<UserEntity(list集合中的类型), String(key map)>
         */
        Map<String, UserEntity> collect = stream.collect(Collectors.toMap(userEntity -> userEntity.getUserName(), userEntity -> userEntity));
        collect.forEach((BiConsumer) (o, o2) -> System.out.println(o + "," + o2));
    }
}

结果:
mayikt,UserEntity{userName='mayikt', age=20}
zhangsan,UserEntity{userName='zhangsan', age=35}
meite,UserEntity{userName='meite', age=28}

Process finished with exit code 0

方法引入

方法引用其实也离不开Lambda表达式, 需要结合lambda表达式能够让代码变得更加精简。

  • 静态方法引入 类名::(静态)方法名称
  • 对象方法引入 类名:: 实例方法名称
  • 实例方法引入 new对象 对象实例::方法引入
  • 构造函数引入 类名::new
类型 语法 对应的Lambda表达式
静态方法引用 类名::staticMethod (args) ->类名.staticMethod(args)
实例方法引用 inst::instMethod (args) ->inst.instMethod(args)
对象方法引用 类名::instMethod (inst,args) ->类名.instMethod(args)
构建方法引用 类名::new (args) ->new 类名(args)

需要遵循一个规范:

引入的方法参数列表、返回类型与函数接口参数列表、返回类型必须要保持一致(对象方法除外)。

方法引入实际上就是lambda表达式中直接引入的方法。

静态方法的引入

举个栗子:

public class Method {
    public static void main(String[] args) {
        // 1.使用匿名内部类的形式 重写get方法,引入静态方法getStaticMethod
          new MessageInterface() {
              @Override
              public void get(Integer a) {
                  Method.getStaticMethod(a);
              }
        }.get(10);

        //2.Lambda表达式中引入静态方法:
        MessageInterface messageInterface2 = (a) -> {
            Method.getStaticMethod(a);
        };
        messageInterface2.get(8);
//静态方法引入可以理解为在Lambda表达式中引入一个静态方法,去实现函数接口中的抽象方法,然后就可以调用接口中 //的这个方法,其实实际执行的是引入的方法.
        //使用方法引入调用方法 必须满足:方法引入的方法必须和函数接口中的方法参数列表/返回值一定保持一致。
        //静态方法getStaticMethod的返回值类型(都是void)和参数列表(都是Integer a)一致,符合方法引入的规范

        //简化:
        MessageInterface messageInterface = Method::getStaticMethod;
        messageInterface.get(6);
    }
    /**
     * Method的静态方法
     */
    public static void getStaticMethod(Integer a) {
        System.out.println("我是静态方法-a的值为:"+a);
    }
}



//函数接口:
@FunctionalInterface
public interface MessageInterface {
    void get(Integer a);
}


结果:
我是静态方法-a的值为:10
我是静态方法-a的值为:8
我是静态方法-a的值为:6

Process finished with exit code 0

实例方法的引入

public class Test009 {
    public static void main(String[] args) {
        Test009 test009 = new Test009();
     //1.匿名内部类的写法
        MessageInterface messageInterface1 = new MessageInterface() {
           @Override
          public void get(Integer a) {
               test009.getT(a);
           }
      };
          messageInterface1.get(1);
        //2.Lambda的写法
        MessageInterface messageInterface = (a) -> {
            test009.getT(a);
        };
        messageInterface.get(2);
        //3.实例方法引入
            MessageInterface messageInterface2 = test009::getT;
        messageInterface2.get(1);
        }

    public void getT (Integer a){
        System.out.println("实例方法引入---get方法:" + a);
    }
    }


   
//函数接口:
@FunctionalInterface
public interface MessageInterface {
    void get(Integer a);
}


结果:
    
实例方法引入---get方法:1
实例方法引入---get方法:2
实例方法引入---get方法:1

Process finished with exit code 0   

构造方法的引入

public class Test011 {
    public static void main(String[] args) {
//      UserInterface userInterface = () -> new UserEntity();
        UserInterface UserInterface2=  UserEntity::new;
        
        UserInterface2.getUser();//调用无参构造,生成一个UserEntity
    }
}
public class UserEntity {
    private String userName;
    private int age;

    public UserEntity() {

    }
    
 //函数接口:
public interface UserInterface {
    UserEntity getUser();
}

对象方法的引入

🎈🎈函数接口中抽象方法的参数是对象

 public static void main(String[] args) {
        // 1.使用匿名内部类的形式
        MayiktService mayiktService = new MayiktService() {
            @Override
            public String get(Test23 t) {
                return t.objGet();
            }
        };
        System.out.println(mayiktService.get(new Test23()));
        // 2.Lambda  t表示对象引用
        MayiktService mayiktService1 = (t) -> t.objGet();
        System.out.println(mayiktService1.get(new Test23()));

        // 3.方法引入 在这时候我们函数接口 第一个参数传递test23 返回调用test23.objGet方法
        MayiktService mayiktService2 = Test23::objGet;
        System.out.println(mayiktService2.get(new Test23()));//执行的是Test23的objGet方法
        //Test23::objGet;----- (t) -> t.objGet();


        // Function中的抽象方法:  R apply(T t); T  apply方法传递的参数类型 : R apply 方法返回的类型
        // 需要将string类型字符串获取长度
        //Function<String, Integer> strFunction = (str) -> {
        //   return str.length();
        // };
        Function<String, Integer> function2 = String::length;
        System.out.println(function2.apply("sovzn"));//执行的是String的length方法
    }


    public String objGet() {
        return "shiyaochang";
    }
}



//函数接口:
public interface MayiktService {
    String get(Test23 test23);
}


结果:
   
shiyaochang
shiyaochang
shiyaochang
5

Process finished with exit code 0

遍历map

public class Map {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("name1", "张三");
        map.put("name2", "李四");
        map.put("name3", "王五");
        map.put("name4", "赵六");
        map.forEach((k, v) ->
                System.out.println(k)
        );
        map.forEach((k, v) ->
                System.out.println(v)
        );
        map.forEach((k, v) ->
                System.out.println(k + ":" + v)
        );
    }
}


name4
name3
name2
name1
赵六
王五
李四
张三
name4:赵六
name3:王五
name2:李四
name1:张三


Process finished with exit code 0