java中stream流使用

lamabda表达式与函数式接口

函数式接口:接口中只有一个未实现的方法
@FuncationalInterface:检查注解,检查写的接口是否是函数式接口
lambda表达式简化了实例的创建
接口MyInterface

@FunctionalInterface//检查注解:检查写的接口是否是函数式接口
public interface MyInterface {

    int sum(int i, int j);

    //默认实现
    default int defaultSum(int i, int j) {
        return i *j;
    }
}

创建匿名实现类(冗余写法)

       MyInterface myInterface1 = new MyInterface() {
            @Override
            public int sum(int i, int j) {
                return i*i + j*j;
            }
        };
        System.out.println(myInterface1.sum(3, 4));

lambda表达式,语法糖,完整写法
只保留动态的内容
语法: (参数列表…) -> {方法体积}

        MyInterface myInterface2 = (int i,int j) -> {
            return i*i + j*j;
        };
        System.out.println(myInterface2.sum(5,6));

简化写法:
参数类型可以不写,只写(参数名…),参数变量名随便定义
参数表最少可以只有一个(),或者只有一个参数名
方法体如果只有一句话,{}可以省略

MyInterface myInterface3 = (i,j) -> i*i + j*j;

lambda表达式使用

入门

         var list = new ArrayList<String>();
        list.add("zyl");
        list.add("hcx");
        list.add("cmh");
        //倒序排列
        Collections.sort(list, (o1,o2) -> o2.compareTo(o1));
        System.out.println(list);

        //:: 引用类中的实例方法
        //只能正序排列
        Collections.sort(list, String::compareTo);

        new Thread(
                () -> System.out.println("hello world")
        ).start();
    }

何时使用lambda表达式:
1.以后调用某个方法传入参数,
这个参数实例是一个接口对象,且只定义一个方法

Function函数式的各种写法

函数式接口:只包含一个抽象方法接口,是支持lambda表达式基础
lambda表达式需要一个目标类型,
这个目标类型必须是一个函数式接口
在这里插入图片描述
函数式接口出入参定义:
1.有入参,无出参
消费者

@FunctionalInterface
public interface BiConsumer<T, U> {

    void accept(T t, U u);
}

使用

        BiConsumer<Integer,Integer> biConsumer = (a,b) -> System.out.println(a+b);
        biConsumer.accept(5,6);

2.有入参,有出参
多功能函数

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);
}

使用

        Function<String,Integer> function1 = str-> Integer.parseInt(str);
        Function<String,Integer> function2 = Integer::parseInt;
        Integer applyInteger = function1.apply("5");

3.无入参,无出参

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

示例:

Runnable runnable = () -> System.out.println("hello");

4.无入参,有出参
数据提供者

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

示例:

        Supplier<String> supplier = ()-> "hello";
        String result = supplier.get();

java.util.function包下的所有funcation定义:
1.consumer 消费者
2.supplier 提供者
3.predicate 断言

        Predicate<Integer> predicate = integer -> 5 == integer;
        boolean isEqual = predicate.test(10);

应用:

    public static void main(String[] args) {
        //1.定义数据提供者函数
        Supplier<String> supplier = () -> "hello world!";
        String dataProvider = supplier.get();

        //2.断言
        Predicate<String> predicate = str -> str.contains("!");
        boolean isTrue = predicate.test(dataProvider);

        //3.转化
        Function<String,String> function = String::toUpperCase;
        String applyUpper = function.apply(dataProvider);
        System.out.println(applyUpper);

        //4.消费
        Consumer<String> consumer = upper -> System.out.println(upper.toLowerCase());
        consumer.accept(applyUpper);

    }

将4步合在一起

        if (predicate.test(supplier.get())) {
            consumer.accept(function.apply(supplier.get()));));
        } else {
            System.out.println(" is false");
        }

Stream Api

声明式处理集合数据:筛选,转换,组合等
创建流->
中间操作(filter,map,flatMap)->新流->
终止操作(count.max)->结果
特性:
懒加载,不用,方法就不会被调用
step1先把数据封装成流,要到数据流
step2.定义流式操作
step3.获取最终结果
1.挑出最大偶数
说明:
filter:过滤出想要的值,如果断言返回true,就是需要的值
intermediate operation,中间操作
中间操作
max: 求最大值,terminal operation 终止操作
终止操作
实现:

        List<Integer> integerList = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        //挑出最大的偶数
        integerList.stream()
                .filter(item -> item % 2 == 0)
                .max(Integer::compareTo)
                .ifPresent(System.out::println);

ifPresent(item -> System.out.println(t))
简化
ifPresent(System.out::println);
全类名::方法名
::简化写法

流的3大部分:
1.数据流
1-1创建流
数据流
concat():合并,将2个流合并成一个流
1-2从集合容器中获取流
List/Set/Map
2.中间操作
流默认是不并发的

        long count = integerList.stream()
                .filter(item -> {
                    System.out.println("filter thread:" + Thread.currentThread().getName());
                    System.out.println("now filter:" + item);
                    return item > 2;
                })
                .count();
        System.out.println(count);

流默认不是并发操作
将流变成并发流

        long count = integerList.stream()
                .parallel()
                .filter(item -> {
                    System.out.println("filter thread:" + Thread.currentThread().getName());
                    System.out.println("now filter:" + item);
                    return item > 2;
                })
                .count();
        System.out.println(count);

并发流
有并发数据将产生并发安全问题,需自行解决多线程安全问题
流的所有所有状态都是无状态,数据状态仅在此函数内有效,不溢出至函数外
错误写法:

        var newList = new ArrayList<Integer>();
        long count = integerList.stream()
                .parallel()
                .filter(item -> {
                    System.out.println("filter thread:" + Thread.currentThread().getName());
                    System.out.println("now filter:" + item);
                    //不能将流中数据溢出至函数外
                    newList.add(item);
                    return item > 2;
                })
                .count();

解决:加锁
脱裤子放屁,别开并发就行

        var newList = new ArrayList<Integer>();
        long count = integerList.stream()
                .parallel()
                .filter(item -> {
                    synchronized (Objects.class) {
                        System.out.println("filter thread:" + Thread.currentThread().getName());
                        System.out.println("now filter:" + item);
                        newList.add(item);
                        return item > 2;
                    }
                })
                .count();

使用线程安全list
也没必要,直接不用并发流就好

        List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<Integer>());
        long count = integerList.stream()
                .parallel()
                .filter(item -> {
                    synchronizedList.add(item);
                    System.out.println("filter thread:" + Thread.currentThread().getName());
                    System.out.println("now filter:" + item);
                    return item > 2;
                })
                .count();

stream中间操作

filter:过滤,挑出要用的元素
map:映射,一一映射,a变成b
mapToInt/mapToLong/mapToDouble
flatMap:散列,一多映射
准备数据
引入lombok依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>

实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private String sex;
    private Integer age;
}

集合:

        List<Person> nameList = List.of(
                new Person("周 一","男",20),
                new Person("王 二","女",22),
                new Person("赵 三","女",33),
                new Person("赵 四","女",18)
        );

filter案例:挑出年龄大于23的人

        nameList.stream()
                .parallel()
                .filter(item -> item.getAge() > 18)
                .forEach(System.out::println);

map案例:拿到这些人的姓名

        nameList.stream()
                .parallel()
                .filter(item -> item.getAge() > 18)
                .map(Person::getName)
                .forEach(System.out::println);

floatMap:一对多

        nameList.stream()
                .parallel()
                .filter(item -> item.getAge() > 18)
                .map(Person::getName)
                .flatMap(item -> {
                    String[] split = item.split(" ");
                    return Arrays.stream(split);
                })
                .forEach(System.out::println);

distinct:去重
sort:排序,默认升序
peek:将所有元素查看一遍,没有返回值,流不会更改
与forEach区别:forEach是结束操作,peek流没有关
limit:要几个元素
taskWhile:满足条件,拿到这个元素/当不满足条件,直接结束流操作

        Stream.of(1,2,3,4,5,6,7,8,9,10)
                .takeWhile( item -> item < 2)
                .forEach(System.out::println);

只打印1
groupBy:分组

        Map<String, List<Person>> groupList = nameList.stream()
                .parallel()
                .filter(item -> item.getAge() > 15)
                .collect(Collectors.groupingBy(Person::getSex));
        groupList.forEach((key, value) -> {
            System.out.println(key + " : " + value);
        });

分组结果

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值