Stream

目录

一 函数式接口

1 特点

2 核心函数式接口

1) Consumer

2) Supplier

3) Function

4) Predicate

5) 扩展:BiFunction

二 Stream

1 stream操作过程

1) 中间操作

2)终端操作

2 创建Stream对象

1) 通过集合获得Stream对象

2) 其他

3 终端操作

forEach()

count() , max() , min()

collect()

4 中间操作

filter()

map()

sorted()

limit() & skip()


一 函数式接口

1 特点

  • 接口中有且仅有一个抽方法

  • 可以使用lambda表达式

  • 可以使用@FunctionalInterface声明接口

  • 在函数式接口中,可以定义多个默认的非抽象方法

2 核心函数式接口

jdk中给我们提供了一些常用的函数式接口

jdk1.8以前,就存在函数式特点接口 : Compartor ,Comparable

jdk1.8以后,提供了一些常用的函数式接口,其中有4个核心接口

1) Consumer

消费型接口 ,传递参数,使用参数做一个处理。没有返回值 void accept(T t);

Consumer mc = (String s1)->{
    System.out.println(s1.length());
};
mc.accept(s);
//-------------------------------------------
Consumer mc1 = (String s1)->{
    System.out.println(s1.length());
};
Consumer mc2 = (String s1)->{
    System.out.println(s1.toUpperCase());
};
Consumer mc3 = s1->{
    System.out.println(s1.substring(0,5));
};
//mc2.accept(s);

//这是一个链式操作,先实现消费功能mc3,再实现消费功能mc2,最后实现消费功能mc1
mc3.andThen(mc2.andThen(mc1)).accept(s);

2) Supplier

供给型接口, 无需要传递参数,返回对象 T get();

//需要产生一个随机数
//创建了一个对象 Object obj = new Object()
Supplier s1 = ()->{
    Random r = new Random();
    return r.nextInt(10);
};
Integer num = s1.get() ;

3) Function

功能型接口,需要传递参数,根据参数做处理,将处理结果返回 R apply(T t); Function

String s = "dmc is good" ;
//需要实现功能,将字符串转换成大小
Function f1 = (String s1)->{
    return s1.toUpperCase();
};
System.out.println( f1.apply(s) );
//---------------------------------------------
String s = "dmc is good" ;
//需要实现功能,将字符串转换成大小
Function f1 = (String s1)->{
    System.out.println("1操作");
    return s1.toUpperCase();
};
//System.out.println( f1.apply(s) );

Function f2 = s1->{
    System.out.println("2操作");
    return s1.substring(0,3);
};

//f1处理后,再进行一次f2的处理
//System.out.println( f1.andThen(f2).apply(s) );
//f1处理前,先进行一次f2的处理
System.out.println( f1.compose(f2).apply(s) );

4) Predicate

断言型接口,传递参数,根据参数做判断,返回boolean boolean test(T t)

//判断user登录信息是否正确
Predicate p1 = (User user1)->{
    return user1.uname.equals("dmc") && user1.upass.equals("123");
};
System.out.println(p1.test(user)?"登录成功":"登录失败");
//----------------------------------------------
User user = new User("dmc","1234") ;
//判断user登录信息是否正确
Predicate p1 = (User user1)->{
    return user1.uname.equals("dmc") ;
};
Predicate p2 = (User user1)->{
    return user1.upass.equals("123") ;
};

//函数式接口中的链式功能,基于的是一个对象
System.out.println(p1.or(p2).test(user)?"登录成功":"登录失败");
System.out.println(p1.negate().test(user));

5) 扩展:BiFunction

R apply(T t,U u); BiFunction

Num num = new Num(10,20);
Function f1 = (num1)->num.x + num.y ;
//------------------------------------------
//二元操作功能
BiFunction b1 = (x , y)-> x+y ;
System.out.println(b1.apply(10,20));

二 Stream

1 stream操作过程

stream操作分为2部分

如果没有终端操作,中间操作无法验证结果。

只有终端操作执行时,中间操作才开始执行。(在终端操作执行前,中间操作只是一个标记)

Stream_第1张图片

 

1) 中间操作

中间操作本身不会执行,只是一个标记,会在终端操作执行时才执行。

中间操作语法会返回一个Stream对象,可以以链式的方式增加多个中间操作(标记)

2)终端操作

要么返回一个具体的数据,要么就执行遍历操作,什么都不返回(void)

整个流操作在执行终端操作方法时就结束了(如果有后续操作,也不是流操作,或者是一个新的流操作)

2 创建Stream对象

1) 通过集合获得Stream对象

jdk1.8之后,为List , Set , Conllection 增加Stream()方法获得流对象

流对象中装载的就是集合中的数据

list.stream()
set.stream()
collection.stream()

2) 其他

//上面我们通过集合获得流的时候是先把数据存到集合里,在获得流的时候将数据存到流里
//下面的这种方法是直接将数据存到流里面
Stream.of(1,2,3,4,5); 
//这种是通过传入一个Supplier,然后通过Supplier返回的对象存入到流中,通过limit的参数表示在流中存入多少个Supplier提供的对象
Stream.generate(()->"dmc").limit(100);
//这种是在流中存入数据1~100
Stream.iterate(1,(i)->++i).limit(100)

3 终端操作

forEach()

参数是个Consumer 消费型接口 
//执行forEach方法时,底层就会遍历每一个元素,每次(底层)遍历获得一个元素,就会调用我们提供的消费功能进行处理(策略模式)
List cars = Arrays.asList(
    new Car("宝马","蓝色",300000),
    new Car("奔驰","黑色",400000),
    new Car("奥迪","红色",450000),
    new Car("保时捷","蓝色",600000),
    new Car("本田","白色",2000000),
    new Car("比亚迪","白色",220000),
    new Car("理想","黑色",250000)
);
cars.stream()
    .forEach(System.out::println);

count() , max() , min()

Object obj = cars.stream()
    .filter(car->car.color.equals("白色"))
    .count();
System.out.println(obj);
//-------------------------------------------
Object obj = cars.stream()
    .max((c1,c2)->c1.price - c2.price);
System.out.println(obj);

collect()

//汇总
//collect终端方法执行时,会遍历所有的元素,会将每个元素的price属性值收集起来,求和
Object obj = cars.stream()
    .collect(Collectors.summingInt(car->car.price));
System.out.println(obj);

//分组(汇总)
Object obj = cars.stream()
    .collect(Collectors.groupingBy(car->car.color));
System.out.println(obj);

Object obj = cars.stream()
    .collect(Collectors.groupingBy(car->{
        if(car.price<=300000){
            return "便宜" ;
        }else{
            return "昂贵" ;
        }
    }));
System.out.println(obj);

4 中间操作

filter()

参数是个Predict 断言型接口  
cars.stream()
    .filter(car->"黑色".equals(car.color))
    .forEach(System.out::println);

map()

参数是函数型接口 Function
//map就是在所有的属性中,抽取出部分需要的属性
//案例中就是在car的3个属性中,抽取出cname和price2个属性
cars.stream()
    .map(car->{return new Car2(car.cname,car.price); })
    .forEach(System.out::println);

List ---> List

sorted()

可以没有参数,默认是按照升序排列的,还有一个带参数的方法Stream sorted(Comparator comparator);
	可以自定义排序规则
//排序  
cars.stream()
    .sorted((c1,c2)->c1.price-c2.price)
    .forEach(System.out::println);

//关于比较器,可以看TreeSet

limit() & skip()

limit(long n1)表示从stream中取出n1的个数
skip(long n2) 表示跳过stream中的前面n2个数
//分页,从那条记录开始,取几条记录, 从0开始取3条(0,1,2),从3开始取3条(3,4,5),从6开始取3条(7,8,9)
cars.stream()
    .sorted((c1,c2)->c1.price-c2.price)
    .skip(4) //跳过几个,因为时从0开始条,这个条过几个,也可以理解为从第几个开始
    .limit(3)
    .forEach(System.out::println);

你可能感兴趣的:(java,开发语言)