Java8新特性

Java8新特性

〇内部类(*)

外部链接链接

〇函数接口

外部链接链接

Function<Integer , Integer> f = Math::abs;
Consumer<String> c = System.out::println;
Supplier<Integer> s = "Hello"::length;
Predicate<String> p = "Hello"::equals;
    
c.accept(s.get().toString());
c.accept(p.test("Hello") && true ? "A":"B");
c.accept(f.apply(-1000).toString());

①Lambda表达式介绍

  1. 在JDK8之前,Java是不支持函数式编程的,所谓的函数编程,即可理解是将一个函数(也称为“行为”)作为一个参数进行传递。
  2. 通常我们提及得更多的是面向对象编程,面向对象编程是对数据的抽象(各种各样的POJO类),而函数式编程则是对行为的抽象(将行为/方法作为一个参数进行传递)。
  3. 在JavaScript中这是很常见的一个语法特性,但在Java中将一个函数作为参数传递这却行不通,好在JDK8的出现打破了Java的这一限制。

②基本的语法规则

**能够接收Lambda表达式的参数类型,是一个只包含一个方法的接口。**只包含一个方法的接口称之为“函数接口”。

1. 无参数,无返回值
new Thread(new Runnable() {
    @Override
   public void run() {
        System.out.println("Hello World!");
    }
 });
//使用Lambda表达式则只需要使用一句话就可代替上面使用匿名类的方式
new Thread(() -> System.out.println("Hello World!"));
2. 有参数,无返回值

Lambda表达式“(x) -> Sysout.out.println(“Hello World” + x)”,左边传递的是参数,此处并没有指明参数类型,因为它可以通过上下文进行类型推导,但在有些情况下不能推导出参数类型(参数是范型的时候),此时则需要指明参数类型 。

public interface FunctionInterface {
     void test(int param);
}
//接口测试
public class FunctionInterfaceTest {
     @Test
     public void testLambda() {
         //使用Lambda表达式代替匿名内部类
         func((x) -> System.out.println("Hello World" + x));
     } 
     private void func(FunctionInterface functionInterface) {
         int x = 1;
         functionInterface.test(x);   
     }
}
3. 有参数,有返回值
public interface FunctionInterface<T> {
     boolean test(T param);
 }
//接口测试
public class FunctionInterfaceTest {
     @Test
     public void testLambda() {
         //使用Lambda表达式代替匿名内部类
         func((Integer x) -> true);
     } 
     private void func(FunctionInterface<Integer> functionInterface{
         int x = 1;
         functionInterface.test(x);
     }
}

此时的Lambda表达式“(Integer x) -> true”,右边是表达式的主体,直接返回true,如果有多行代码,则可以直接使用花括号表示,例如:

func((Integer x) -> {
    System.out.println("Hello World" + x);
    return true;
});
4.小结

这三种基本情况已经大致清楚了,特别是需要弄清,什么时候可以使用Lambda表达式代替匿名内部类,也就是Lambda表达式的应用场景是函数接口。Lambda表达式这一新特性在JDK8中的引入,更大的好处则是集合API的更新,新增的Stream类库,使得我们在遍历使用集合时不再像以往那样不断地使用for循环。

2.Stream流遍历集合

①流介绍

  1. 流是 JDK8 新增的成员,允许以声明性方式处理数据集合,可以把 Stream 流看作是遍历数据集合的一个高级迭代器 。

  2. stream的操作可以分为两类,中间操作(intermediate operations)和结束操作(terminal operations):

    1. 中间操作总是会惰式执行,调用中间操作只会生成一个标记了该操作的新stream。
    2. 结束操作会触发实际计算,计算发生时会把所有中间操作积攒的操作以pipeline的方式执行,这样可以减少迭代次数。计算完成之后stream就会失效。
  3. 虽然大部分情况下stream是容器调用Collection.stream()方法得到的,但stream和collections有以下不同:

    1. 无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
    2. 为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
    3. 惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
    4. 可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。

②获取stream

// 1、数组
   String[] arr = new String[]{"ab", "cd", "ef"};
   Stream<String> arrStream = Arrays.stream(arr);
   // 2、集合
   List<String> list = Arrays.asList("ab", "cd", "ef");
   Stream<String> colStream = list.stream();
   // 3、值
   Stream<String> stream = Stream.of("ab", "cd", "ef");

③stream方法使用

测试数据:

List<User> list = Arrays.asList(
     // name,age
      new User("张三", 11),
      new User("王五", 20),
      new User("王五", 91),
      new User("张三", 8),
      new User("李四", 44),
      new User("李四", 44),
      new User("李四", 44)
  );
1.forEach()

使用该方法迭代流中的每个数据

/**
   * forEach 迭代输出每条数据.
   */
  @Test
  public void testForEach(){
    // java 8 前
    System.out.println("java 8 前");
    for(User user: list){
      System.out.println(user);
    }
    // java 8 lambda
    System.out.println("java 8 lambda");
    list.forEach(user -> System.out.println(user));
 
    // java 8 stream lambda
    System.out.println("java 8 stream lambda");
    list.stream().forEach(user -> System.out.println(user));
  }
2.sorted()

使用该方法排序数据

/**
   * sort 排序.
   */
  @Test
  public void testSort() {
    System.out.println("-----排序前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----排序后-----");
    // java 8 前
    System.out.println("java 8 前");
    Collections.sort(list, new Comparator<User>() {
      @Override
      public int compare(User o1, User o2) {
        return o1.getAge().compareTo(o2.getAge());
      }
    });
    for (User user : list) {
      System.out.println(user);
    }
    // java 8 stream 方法引用
    System.out.println("java 8 stream 方法引用");
  list.stream().sorted(Comparator.comparing(User::getAge)).forEach(user -> System.out.println(user));
}
3.filter()

使用该方法过滤

/**
   * filter 过滤.
   */
  @Test
  public void testFilter(List<User> list) {
    // 输出年龄大于50的人
    System.out.println("-----过滤前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----过滤后-----");
    // java 8 前
    System.out.println("java 8 前");
    for(User user: list){
      if (user.getAge() > 50) {
        System.out.println(user);
      }
    }
    // java 8 stream
    System.out.println("java 8 stream");
    list.stream().filter((User user) -> user.getAge() > 50).forEach(user -> System.out.println(user));
}
4.limit()

使用方法截断

/**
   * limit 截断.
   */
  @Test
  public void testLimit() {
    // 从第三个开始截断,只输出前三个
    System.out.println("-----截断前-----");
    list.forEach(user -> System.out.println(user));
    System.out.println("-----截断后-----");
    // java 8 前
    System.out.println("java 8 前");
    for (int i = 0; i < 3; i++) {
      System.out.println(list.get(i));
    }
    // java 8 stream
    System.out.println("java 8 stream");
    list.stream().limit(3).forEach(user -> System.out.println(user));
}
5.map()
//将指定方法应用到每个元素上
.map(Transaction::getYear)
6.distinct()
去重
7.collect()
//收集成集合
.collect(toList())

3.应用测试

①Trader类
package Lambda;

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @author mingxian.wen@hand-china.com
 * @description:
 * @create 2019-09-03 14:14
 */
@Data
@AllArgsConstructor
public class Trader {

  private String name;
  private String city;
}
②Transaction类
package Lambda;

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @author mingxian.wen@hand-china.com
 * @description:
 * @create 2019-09-03 14:15
 */
@Data
@AllArgsConstructor
public class Transaction {

  private Trader trader;
  private int year;
  private int value;
}
③主函数
package Lambda;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;

import java.util.*;

/**
 * @author mingxian.wen@hand-china.com
 * @description:
 * @create 2019-09-03 14:15
 */
public class LambdaMain {
  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> transactions = Arrays.asList(
      new Transaction(brian, 2011, 300),
      new Transaction(raoul, 2012, 1000),
      new Transaction(raoul, 2011, 400),
      new Transaction(mario, 2012, 710),
      new Transaction(mario, 2012, 700),
      new Transaction(alan, 2012, 950)
  );

  /*找出2011年发生的所有交易,并按交易额排序*/

  public void T1() {
    List<Transaction> list = transactions.stream()
        //.map(Transaction::getYear)
        .filter((t) -> t.getYear() == 2011)
        .sorted(comparing(Transaction::getValue))
        .collect(toList());
    /*.forEach(System.out::println);*/
    list.forEach(System.out::println);
  }


  /*交易员在哪些不同的城市工作过*/

  public void T2() {
    List<String> list = transactions.stream()
        //.map(Transaction::getTrader)
        //.map(Trader::getCity)
        .map((t) -> t.getTrader().getCity())
        .distinct()
        .collect(toList());
    list.forEach(System.out::println);
  }

  /*查找所有来自剑桥的交易员,并按姓名排序*/

  public void T3() {
    List<Trader> list = transactions.stream()
        .map(Transaction::getTrader)
        .distinct()
        .filter((t) -> "Cambridge".equals(t.getCity()))
        .sorted(comparing(Trader::getName))
        .collect(toList());
    list.forEach(System.out::println);
  }


  /*返回所有交易员的姓名字符串,并按字母顺序排序*/

  public void T4() {
    String str = transactions.stream()
        .map((t) -> t.getTrader().getName())
        .distinct()
        .sorted()
        .reduce("", (s1, s2) -> s1 + s2 + " ")
        .trim();
    System.out.println(str);
  }

  /*有没有交易员在米兰工作的?*/

  public void T5() {
    List<String> list = transactions.stream()
        .map(Transaction::getTrader)
        .distinct()
        .filter((t) -> "Milan".equals(t.getCity()))
        .map(Trader::getName)
        .collect(toList());
    list.forEach(System.out::println);
    boolean anyMatch = transactions.stream()
        .anyMatch((t) -> "Milan".equals(t.getTrader().getCity()));
    System.out.println(anyMatch);
  }

  /*打印生活在剑桥的交易员的所有交易额*/

  public void T6() {
    List<Integer> list = transactions.parallelStream()
        .filter((t) -> "Cambridge".equals(t.getTrader().getCity()))
        .map(Transaction::getValue)
        .collect(toList());
    list.forEach(System.out::println);
  }

  /*所有交易中,最高的交易额是多少*/

  public void T7() {
    Integer value = transactions.stream()
        //.max(Comparator.comparing(Transaction::getValue))
        .map(Transaction::getValue)
        .reduce(0,Integer::max);
    System.out.println(value);
  }

  /*找到交易额最小的交易*/

  public void T8() {
    Transaction transaction = transactions.stream()
        .min(Comparator.comparing(Transaction::getValue))
        .orElse(null);
    System.out.println(transaction);
  }

  public static void main(String[] args) {
    LambdaMain lambdaMain = new LambdaMain();
    lambdaMain.T8();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值