Java8新特性笔记

目录

Lambda表达式

Stream流

时间api

Lambda表达式

public void fun1() {
    String spt=","; //lambda表达式会将变量转换为final类型
//    final String spt = ",";
//(String e)显示声明参数 e 的类型  可忽略 
    Arrays.asList("a", "b", "c").forEach((String e) -> {
      System.out.print(e + spt);
    });
  }

@functionalInterface 函数式接口声明

  • 1,如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
  • 2,如果我们在一个接口上声明了@FunctionalInterface注解,那么编译器就会
    按照函数式接口的定义来要求该接口
  • 3,如果接口只有一个抽象方法,但我们没有声明@FunctionInterface注解,那么
    编译器依旧会将该接口看做成函数式接口
  • 4 接口中的抽象方法间接或直接重写Object类中的方法,该接口中的抽象方法个数不会增加
@FunctionalInterface
public interface MyInterface {
  void test();
  /*抽象方法重写object类中的方法 不会使得该接口的抽象方法个数加1*/
  /*所以@FunctionalInterface不会报错,符合函数式接口的定义*/
  String toString();
  boolean equals(Object o);
}

函数式接口的例子

  • 接口采用上面第四点的接口
public class FunctionalInterfaceDemo {

  public void test1(MyInterface myInterface) {
    myInterface.test();
    System.out.println("----------------------");
  }

  public static void main(String[] args) {
    FunctionalInterfaceDemo functionalInterfaceDemo = new FunctionalInterfaceDemo();
    /*采用匿名内部类的方式 实现接口*/
    functionalInterfaceDemo.test1(new MyInterface() {
      @Override
      public void test() {
        System.out.println("实现类");
      }
    });
    /*采用lambda表达式的方法 实现接口*/
    /*抽象方法没有参数 这必须 使用() */
    functionalInterfaceDemo.test1(  () -> {
      System.out.println("lambda实现类");
     
    });

  }
}

函数式接口 比如 : Consumer类,Runnable类


Function函数式接口的使用

public class FunctionTest {

  /*行为的描述*/
  public int compute(int a, Function<Integer, Integer> function) {
    /*function函数式接口的一个抽象方法,给定一个值,返回一个值*/
    return function.apply(a);
  }

  public String resultString(Integer s, Function<Integer, String> function) {
    return function.apply(s);
  }

  /*传统的写法  先定义行为*/
  public int add(int a) {
    return a + a;
  }
  /* 调用function接口的 compose方法*/
  public int computeBefore(int a, Function<Integer, Integer> function1,
      Function<Integer, Integer> function2) {
    /*先运行function2.apply(a),把结果当参数再放入到function1.apply(a)中*/
    return function1.compose(function2).apply(a);
  }
  /* 调用function接口的 andThen方法*/
  public int computeAfter(int a, Function<Integer, Integer> function1,
      Function<Integer, Integer> function2) {
    /*先运行function1.apply(a),把结果当参数再放入到function2.apply(a)中*/
    return function1.andThen(function2).apply(a);
  }

  public static void main(String[] args) {
    FunctionTest functionTest = new FunctionTest();
    /*lambda表达式 传递行为*/
    System.out.println(functionTest.compute(2, data -> data * data));
    System.out.println(functionTest.resultString(8, value -> String.valueOf(value + "toString")));
    /*行为已经定义死了 只是一个面向对象的过程 , 而函数式编程 是 传递行为*/
    System.out.println(functionTest.add(5));
    /*也可以事先定义好行为*/
    Function<Integer, String> action = data -> data.toString();
    System.out.println(functionTest.resultString(10, action));
    /*定义compose andThen 的行为*/
    System.out.println(functionTest.computeBefore(10, e -> e * e, e -> e + e));
    System.out.println(functionTest.computeAfter(10, e -> e * e, e -> e + e));
  }
}

BiFunction 函数式接口的使用

public class BiFunctionTest {

  public Integer compute(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) {
    return biFunction.apply(a, b);
  }

  public Integer compute(int a, int b, BiFunction<Integer, Integer, Integer> biFunction1,
      Function<Integer, Integer> Function2) {
    return biFunction1.andThen(Function2).apply(a, b);
  }

  public static void main(String[] args) {
    BiFunctionTest biFunctionTest = new BiFunctionTest();
    System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 + e2));
    System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 / e2));
    System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 * e2));

    System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 + e2, e3 -> e3 * e3));
  }
}

predicate 函数式接口

public class PredicateTest {
  /***
   * 给定一个参数 判断条件 满足就返回true 否则 false
   * @see Predicate#test(java.lang.Object)
   */
  public static void main(String[] args) {
    Predicate<String> predicate = e -> e.length()>5;
    System.out.println(predicate.test("Memory"));
  }
}

and方法 or方法 negate方法

  /*predicate接口 其他方法的用法*/
  public void conditionFilter(List<Integer> list,Predicate<Integer> predicate1,Predicate<Integer> predicate2){
    for (Integer integer : list) {
      /* and 方法  两个都要满足*/
      /*or 方法 满足其中一个即可*/
      /*negate 方法 取相反*/
      if (predicate1.and(predicate2).test(integer)){
      /* predicate1.or(predicate2).test(integer)*/
      /*predicate1.and(predicate2).test(integer)*/
      /*predicate1.and(predicate2).negate().test(integer)*/
        System.out.println(integer);
      }
    }
  }

  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    PredicateTest predicateTest = new PredicateTest();
    /*给定函数具体行为*/
    predicateTest.conditionFilter(list,e ->e % 2 == 0);
    System.out.println("- - - - - - - - - - - -");
    predicateTest.conditionFilter(list,e -> e % 2 != 0);
    System.out.println("- - - - - - - - - - - - ");
    predicateTest.conditionFilter(list,e2 -> e2<8,e1 -> e1 % 2 ==0);
  }

Supplier 函数式接口 get()方法的使用

  • 没有参数 返回一个结果,使用场景可以是创建各种工厂等等
public class SupplierTest {
  /*Supplier函数接口中 get()方法的使用*/
  public void get(Supplier<String> supplier){
    System.out.println(supplier.get());
  }

  public static void main(String[] args) {
    SupplierTest supplierTest = new SupplierTest();
    Supplier supplier = () -> "hello world";
    supplierTest.get(supplier);
    System.out.println("-------------------");
    /*使用场景一  返回一个对象*/
    Supplier<Person> supplier1 = () -> new Person();
    System.out.println(supplier1.get().getClass());
    /*使用构造方法调用 返回一个对象*/
    Supplier<Person> supplier2 = Person::new;
    System.out.println(supplier2.get().getClass());
  }
}

BinaryOperator 函数式接口

  • 该接口是bifunction的子类,是一个特殊的bifunction,bifunction是给定两个参数返回一个结果,这三个变量都是可以类型不一样的。但binaryOperator三个变量的类型都必须是一致的
public class BinaryOperatorTest {

  /*binaryOperator()方法的使用*/
  public Integer counter(Integer i , Integer b , BinaryOperator<Integer> binaryOperator){
    return binaryOperator.apply(i,b);
  }
  /*BinaryOperator静态方法的使用*/
  public String getMinString (String s2,String s1,Comparator<String> comparator){
    return BinaryOperator.minBy(comparator).apply(s1,s2);
  }
  public String getMaxString (String s2,String s1,Comparator<String> comparator){
    return BinaryOperator.maxBy(comparator).apply(s1,s2);
  }
  public static void main(String[] args) {
    BinaryOperatorTest binaryOperatorTest = new BinaryOperatorTest();
    Integer counter = binaryOperatorTest.counter(10, 15, (e1, e2) -> e1 * e2);
    System.out.println(counter);
    System.out.println("-----------------------------------");
    System.out.println(binaryOperatorTest.getMinString("hhh","aaaa",(e1,e2) ->e1.length()-e2.length()));
    System.out.println(binaryOperatorTest.getMaxString("aaahhhaaaaa","aaaa",(e1,e2) ->e1.length()-e2.length()));
  }
}

Optional 类 详解

/**
*author huangh
*date 2018/10/14 16:02
*description Optional 是为了规避 常见的 空指针异常
*/
public class OptionalTest {

  public static void main(String[] args) {
    /*Optional 类 中的构造方法是私有的 因此不能 直接new
    有三个构造对象 静态方法
    of(value)  带参数
    empty()  构造一个空的
    ofNullable() 可以为空 也可以不为空
    */
    Optional<String> optional = Optional.of("hello");
    /*判断不为空才会执行下面的语句,替代 if(not null)*/
    optional.ifPresent( e -> {
      //do something
      System.out.println(e);
    });
    /*如果optional容器里面的value为null的话就执行这条语句*/
    System.out.println(optional.orElse("world"));

  }
}
  • 模仿使用场景(进阶):

先定义 一对多 animal类 和 tom类

public class OptionalTest2 {

  public static void main(String[] args) {
    Tom tom = new Tom();
    tom.setName("bob");
    Tom tom1 = new Tom();
    tom1.setName("lily");

    List<Tom> toms = Arrays.asList(tom, tom1);
    Animal animal = new Animal();
    animal.setTomList(toms);

    Optional<Animal> optional  = Optional.ofNullable(animal);
    System.out.println(
        /*如果容器中的value不为空就会执行 e ->e.getTomList() 否者 就是执行 orElse*/
        optional.map( e -> e.getTomList()).orElse(Collections.emptyList())
    );

  }
}

方法引用

  • 引用静态方法 ContainingClass::staticMethodName

  • 引用某个对象的实例方法 containingObject::instanceMethodName

  • 引用某个类型的任意对象的实例方法 ContainingType::methodName

  • 引用构造方法 ClassName::new

public class MethodReferenceTest {

  @Test
  public void printlnTest() {
    List<Integer> list = Arrays.asList(1, 2, 3, 5);
    /*lambda表达式*/
    list.forEach((e) -> System.out.println(e));
    /*方法引用*/
    list.forEach(System.out::println);
  }

  @Test
  /* 方法引用: 静态引用*/

  public void StaticClassReference() {
    Student student1 = new Student("zhangsan", 15);
    Student student2 = new Student("lishi", 52);
    Student student3 = new Student("zhaoliu", 99);
    List<Student> students = Arrays.asList(student1, student2, student3);
    //  students.sort((e1,e2) ->Student.compareStudentByScore(e1,e2));
    //  students.forEach(e -> System.out.println(e.getScore()));

    students.sort(Student::compareStudentByScore); // 静态方法引用
    students.forEach(e -> System.out.println(e.getScore()));
  }

  @Test
  /*方法引用代替lambda表达式*/
  public void referenceTest() {

    Function<String, Integer> stringToInteger = Integer::parseInt;
    //        (String s) -> Integer.parseInt(s);

    BiPredicate<List<String>, String> contains = List::contains;
    //        (list, element) -> list.contains(element);

    Supplier<Student> supplier = Student::new;
    //    () -> new Student()

  }
}

Stream流

他人的学习笔记

  • Colletion提供了新的Stream方法

  • Stream流不储存值,以管道的方式获取值

  • 本质是函数式的,对流的操作会生成一个结果,不会改变底层的数据源,集合可以作为底层的数据源

特点

  • 只能遍历一次

我们可以把流想象成一条流水线,流水线的源头是我们的数据源(一个集合),数据源中的元素依次被输送到流水线上,我们可以在流水线上对元素进行各种操作。一旦元素走到了流水线的另一头,那么这些元素就被“消费掉了”,我们无法再对这个流进行操作。当然,我们可以从数据源那里再获得一个新的流重新遍历一遍。

  • 采用内部迭代

若要对集合进行处理,则需我们手写处理代码,这就叫做外部迭代。而要对流进行处理,我们只需告诉流我们需要什么结果,处理过程由流自行完成,这就称为内部迭代。

流的操作

  • 中间操作(惰性取值,只有在终端方法调用才会执行)

当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。
中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。

  • 终端操作(及早取值)

当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终端操作。
终端操作将返回一个执行结果,这就是你想要的数据。

流的操作过程

  • 1 准备数据源
  • 2 执行中间操作

中间操作可以有多个,它们可以串连起来形成流水线。

  • 3 执行终端操坐

执行终端操作后本次流结束,你将获得一个执行结果。

  • 创建stream流
/*创建Stream流*/
  public void of() {
     /*of方法 返回一个参数类型的stream 带有任意参数的集合*/
    Stream<String> helloStream = Stream.of("hello", "world");
    List<String> collectList = helloStream.map(e -> e.toUpperCase()).collect(Collectors.toList());
    collectList.forEach(System.out::println);

    /*创建一个不含任何原属的Stream*/
    Stream<Object> empty = Stream.empty();

    /*基本使用 数据源--中间操作--及早求值*/
    List<Integer> list2 = Arrays.asList(1, 1, 2, 3, 4, 5, 6);
//    System.out.println(list2.stream().map(e -> e + 2).reduce(Integer::sum).get());
  }
  • 生成无限的stream流
/*Stream接口两个用来创建无限Stream的静态方法*/
  public void generateAndIterate() {
    /*返回无限的无序stream流*/
    Stream<String> generate = Stream.generate(() -> String.valueOf(3));
    //    generate.forEach(System.out::println);
    /*返回无限的无序随机数字*/
    Stream<Double> generate1 = Stream.generate(Math::random);
    //    generate1.forEach(System.out::println);
    /*创建一个有序的stream流 {1,2,3,4...}*/
    Stream<BigDecimal> iterate1 = Stream.iterate(BigDecimal.ZERO, e -> e.add(BigDecimal.ONE));
    //    iterate1.forEach(System.out::println);
  }

Stream filter(Predicate<? super T> predicate)

filter方法的练习

/**
*author huangh
*date 2018/10/13 10:10
*description Predicate 接口的练习
*/
public class PredicateTest {
  @Test
  /***Stream API  filter 的使用*
  *返回满足Predicate的 Stream*
  * @see Stream#filter(java.util.function.Predicate)
  */
  public void filter(String username){
    Person person1 = new Person("bob",21);
    Person person2 = new Person("lily",21);
    Person person3 = new Person("kevin",21);
    List<Person> people = Arrays.asList(person1, person2, person3);
    List<Person> filterPeople = people.stream().filter(e -> e.getUsername().equals(username))
        .collect(Collectors.toList());
//    filterPeople.forEach(e -> System.out.println(e));
    System.out.println(filterPeople);
  }

  /**
   * 对年龄的筛选
   * BiFunction 给两个参数返回一个结果
   *  Stream API 对filter的使用
   */
  public List<Person > filter(Integer age,List<Person> people) {
    BiFunction<Integer,List<Person>, List<Person>> biFunction = (ageOfPerson,peopleList) ->
       people.stream().filter(e ->e.getNum().equals(age)).collect(Collectors.toList());
    return biFunction.apply(age,people);
  }

  /*先定义好行为的描述*/
  public List<Person> filter (Integer age ,List<Person> people, BiFunction<Integer,List<Person>, List<Person>> biFunction){
    return biFunction.apply(age,people);
  }


  public static void main(String[] args) {
    Person person1 = new Person("bob",21);
    Person person2 = new Person("lily",212);
    Person person3 = new Person("kevin",213);

    PredicateTest PredicateTest = new PredicateTest();
    PredicateTest.filter("bob");

    List<Person> people = Arrays.asList(person1, person2, person3);
    List<Person> filter = PredicateTest.filter(212, people);
    System.out.println(filter);
    System.out.println("-------------------------------------");

    /*先定义具体的行为 这样比前两个的方法 跟为灵活*/
    List<Person> list = PredicateTest.filter(20,people,(ageOfPerson,personList) ->
     people.stream().filter(e -> e.getNum()>20).collect(Collectors.toList())
    );
    System.out.println(list);
  }
}

Stream 的短路 现象

public void fun() {
    List<String> list = Arrays.asList("hello", "world", "welcome");
    list.stream()
        .map(e -> {
              int length = e.length();
              /*这里不会把每个都打印,会出现短路。只要符合条件则后面的元素都不执行*/
              System.out.println(e);
              return length;})
        .filter(length -> length == 5)
        .findFirst()
        .ifPresent(System.out::println);
  }

map 和 flatmap

  @Test
  public void flatMap() {
    List<String> list = Arrays.asList("hello world", "hey new year", "welcome the world");
    /*此处map会返回一个Stream<String[]> 然后再对其 去重*/
    list.stream().map(string -> string.split(" ")).distinct().forEach(System.out::println);
    /*先根据split分词,把Stream<String[]> 使用 flatMap(Arrays::stream) 转换为Stream<String> */
    list.stream().map(string -> string.split(" ")).flatMap(Arrays::stream).
        distinct().forEach(System.out::println);
  }

Stream 和 ParallelStream

 @Test
  /*串行流 与 并发流*/
  public void parallelStream(){
    List<String> list = new ArrayList<>();
    for (int i = 0;i<2000000;i++){
      list.add(UUID.randomUUID().toString());
    }
    System.out.println("开始排序");
    long start = System.nanoTime();
//  list.stream().sorted().count(); 大约花费两秒
    list.parallelStream().sorted().count(); //大约花费一秒
    long end =  System.nanoTime();
    System.out.println(TimeUnit.NANOSECONDS.toMillis(end-start));
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值