Java8之Stream

Wesley13
• 阅读 797

在使用Stream之前先介绍几个概念:1、函数式接口 2、常用的函数式接口 3、Lambda 4、方法引用

1、函数式接口

  1.只定义了一个抽象方法的接口。
  2.JDK8接口中的静态方法和默认方法,都不算是抽象方法。
  3.接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。

@FunctionalInterface
public interface Runnable {
  public abstract void run();
}

2、常用的函数式接口

  1.Predicate
  接口接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。
  boolean test(T t);  例:Predicate p = s -> s.equals(“hello”);  p.test(“hello”);  

  2.Consumer接口接受一个T类型参数,没有返回值。

  void accept(T t);  例:Consumer c = i-> System.out.println(i);  Stream.of(1,2,3,4).forEach(c);

  3.Supplier 接口没有入参,返回一个T类型的对象,类似工厂方法。 T get();

  4.Function<T,R > 对类型为T的对象应用操作,并返回结果,结果是R类型的对象  R apply(T t);

  5.UnaryOperator extends Function<T, T> 对类型为T的对象应用操作,并返回结果,结果是T类型的对象   T apply(T t);

  6.BiFunction<T,U,R> 接口对类型为T和U的对象应用操作,返回类型为R的对象。 R apply(T t, U u);

  7.BinaryOperator extends BiFunction<T,T,T> 接口对两个类型为T的对象应用操作,返回类型为T的对象。T apply(T t, T t);

  8.Comparator比较两个类型为T的对象,返回int类型。int compare(T o1, T o2);

3、Lambda

public static void main(String[] args) {
  int c = 10;
  MathOperation m = (a,b)->a+b+c;//编译报错
  c = 1;
}
interface MathOperation {
  int operation(int a, int b);
}

4、方法引用

格式:::

四种不同类型的方法引用:

  引用静态方法 ContainingClass::staticMethodName 例: String::valueOf,对应的Lambda:(s) -> String.valueOf(s) 

  引用特定对象的实例方法 containingObject::instanceMethodName 例子: x::toString,对应的Lambda:() -> this.toString()

  引用特定类型的任意对象的实例方法 ContainingType::methodName 例子: String::toString,对应的Lambda:(s) -> s.toString() 

  引用构造函数 ClassName::new 例子: String::new,对应的Lambda:() -> new String() 

5、Optional类

Optional 类主要解决的问题是空指针异常,它本质上是包含有可选值的包装类,可以含有对象也可以为空
常用方法:
  isPresent() – 如果有值则返回true
  get() – 如果值存在则返回值
  orElse(T other) –如果值存在则返回值,否则返回other
  ifPresent(Consumer<? super T> consumer) – 如果值存在,则执行consumer

Optional<String> optional = Optional.of("hello");
if (optional.isPresent()){
    String hello = optional.get();
}
String world = optional.orElse("world");

6、Stream

Stream的工作方式 https://www.ibm.com/developerworks/cn/java/j-java-streams-3-brian-goetz/fuse.svg,Stream的中间参数一般为常用函数式接口,因此理解函数式接口之后就能很好的使用Stream。

Arrays.asList("hello", "world", "hello world").stream().mapToInt(item -> {     int length = item.length();     System.out.println(item);     return length;}).filter(length -> length == 5).findFirst().ifPresent(System.out::println);

   1.Stream的创建

//从单个元素创建 
Stream.of(val1, val2, …)
//从集合创建
someList.stream()
//从数组创建  
Stream.of(someArray)
Arrays.stream(someArray)
//创建无限流
IntStream.range(0,100)
IntStream.iterate(0, i -> i + 1)

  2.中间操作

Stream.of(“abc”, “”, “bc”, “efg”).filter(string - > !string.isEmpty()).collect(Collectors.toList());

Arrays.asList(3, 2, 2, 3, 7, 3, 5).stream().map(i-> i*i).distinct().collect(Collectors.toList());

IntStream.range(0,100).limit(10).forEach(System.out::println); 

Stream.of(1,2,3,4,5,6).peek(n-> System.out.println(n*2)).map(n->n+"h").forEach(System.out::println) ;

Stream.of(5,8,7,3,4,1,9).sorted(Integer::compare).forEach(System.out::println);Stream.of(5,8,7,3,4,1,9).sorted((a,b)->a-b).forEach(System.out::println);

students.stream().sorted(Comparator.comparingInt(Student::getAge).reversed().thenComparing(Student::getName)).forEach(System.out::println);

List<String> list1 = Arrays.asList("a","b","c");
List<String> list2 = Arrays.asList("d","e","c");List<String> list3 = Arrays.asList("f","g","c");List<List<String>> list = Arrays.asList(list1,list2,list3);List<String> result = list.stream().flatMap(stringList->stringList.stream()).distinct().collect(Collectors.toList())

  3.终端操作

Stream.of(5,8,7,3,4,1,9).min(Integer::compareTo).get() ;
Stream.of(5,8,7,3,4,1,9).max(Integer::compareTo).get() ;
Stream.of(5,8,7,3,4,1,9).anyMatch(num->num==9);
Stream.of(5,8,7,3,4,1,9).allMatch(num->num==9);
Stream.of(5,8,7,3,4,1,9).count();
Stream.of(5,8,7,3,4,1,9).findAny().get();
Stream.of(5,8,7,3,4,1,9).findFirst().get();
/*Reduce:从一个作为累加器的初始值开始,利用binaryOperator与流中的元素逐个结合,从而将流归约为单个值 。reduce操作每处理一个元素总是创建一个新值*/
Stream.of(5,8,7,3,4,1,9).reduce(1,(sum,item)->sum+item);
Stream.of(5,8,7,3,4,1,9).reduce(Integer::sum).get();
/*Collect:接收的参数是将流中的元素累积到汇总结果的各种方式(称为收集器)。修改现存的值,而不是每处理一个元素,创建一个新值*/
students.stream().map(student -> student.getName()).collect(Collectors.toList());
students.stream().map(student -> student.getName()).collect(Collectors.toSet());
students.stream().collect(Collectors.toMap(s1 -> s1.getName(), s2 -> s2.getAge()));
Map<String, List<Student>> map = students.stream().collect(Collectors.groupingBy(Student::getName));

  4.一个比较好用的case

//多线程处理有序的集合
IntStream.range(0, files.size()).parallel().forEach(fileIndex -> {do something about files});
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java Lambda表达式
简介  Lambda可以理解为简洁的表示可传递的匿名函数,包括:参数列表、函数主体、返回类型、抛出的异常列表(可以不存在)。  函数式接口:定义一个抽象方法的接口(接口可以拥有默认方法:default)。  函数式接口有什么用?    Lambda可以以内联的形式为函数式接口的抽象方法提供实现。虽然内部类也可以实现,但lambda表达
Wesley13 Wesley13
3年前
java8中接口中的default方法
在java8以后,接口中可以添加使用default或者static修饰的方法,在这里我们只讨论default方法,default修饰方法只能在接口中使用,在接口种被default标记的方法为普通方法,可以直接写方法体。实现类会继承接口中的default方法如果接口A中有default方法:publicinterfaceA{publi
Wesley13 Wesley13
3年前
java 07 接口
1.interface    接口2.接口中的成员修饰符固定  publicstaticfianl  //成员变量  只通过类访问   publicabstract    //成员函数   3.接口里所有的方法都是抽象的,抽象类中,可以没有抽象方法。  类与类继承,类与接口是实现的关系。降低耦合(高
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
3年前
Java8—一万字的Lambda表达式的详细介绍与应用案例
  基于Java8详细介绍了lambda表达式的语法与使用,以及方法引用、函数式接口、lambda复合等Java8的新特性!文章目录1Lambda的概述2函数式接口2.1Consumer消费型接口2.2Supplier供给型接口2.3Function<T,R函数型接口
Wesley13 Wesley13
3年前
Java8新特性学习
1简述公司自年初终于开始使用java8作为项目的标准jdk,在开发过程中,逐渐认识到java8的很多新特性,确实很方便.其中内容的核心,在于函数式编程,即将函数本身作为对象参数去处理.其中涉及到三个关键新特性:1.lambda表达式(及函数式接口)2.stream3.方法引用这三个新特性的使用是相辅相
Wesley13 Wesley13
3年前
Java 接口基础详解
目录Java接口示例实现一个接口接口实例实现多个接口方法签名重叠接口变量接口方法接口默认方法接口与继承继承与默认方法接口与多态性在Java中,接口是一个抽象类型,有点类似于类,但Java接口只能包含方法签名与属性,
Wesley13 Wesley13
3年前
Java8 新特性 函数式接口
什么是函数式接口  函数式接口是Java8引用的一个新特性,是一种特殊的接口:SAM类型的接口(SingleAbstractMethod)。但是它还是一个接口,只是有些特殊罢了。  函数式接口的出现主要是为了配合Java8的另一个新特性Lamdba表达式来使用。接口中只有一个抽象方法接口