Stream流和Iterator以及Optional

Iterator

Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayListHashSet 等集合,foreach底层也是一个迭代器,集合的的删除操作要在迭代器中进行操作,拿ArrayList举例,底层是数组结构,在进行元素删除的时候,后边的元素要前移一位,这时候对应索引上的值发生了变化,如下,若在循环中进行删除操作之后,当前索引位置i上的值被删除,i+1索引位置上的值会自动移到i上,i+1的值变成i+2索引位置的值,在进行i+1索引位置的值删除的是原i+2的值,而原i+1位置上的值已经在原i位置上,可能造成漏删。

 ArrayList<String> s = new ArrayList<>();
        s.add("1");
        s.add("2");
        s.add("3");
        s.add("4");
        s.add("5");
System.out.println(s.get(2));//3
        s.remove(2);
System.out.println(s.get(2));//4

迭代器 it 的两个基本操作是 next 、hasNext 和 remove。

ArrayList<Integer> numbers = new ArrayList<Integer>();
        numbers.add(12);
        numbers.add(8);
        numbers.add(2);
        numbers.add(23);
        Iterator<Integer> it = numbers.iterator();
        while(it.hasNext()) {
            Integer i = it.next();
            if(i < 10) {  //次数的判断条件有时候可以结合stream流进行代替
                it.remove();  // 删除小于 10 的元素
            }
        }
        System.out.println(numbers);
    }

迭代器的内部有两个计数的变量,初始位置是在-1位置开始的,一般是it.hasNext() ,有的话,it.next(),返回值是集合的一个元素,因为是从-1开始的所以集合的下一个索引位置上的元素是0索引位置的,然后it.remove(),删除当前满足条件的元素。

Stream

Stream相当于Iterator的高级使用,提供一个内部迭代方式

分为三部分:创建流,转换流,聚合

创建流的操作方式:

Collection接口提供了构建流的方法:stream() 方法

Stream接口的静态工厂方法

转换流

distinct:

对于Stream中包含的元素进行去重操作(去重逻辑依赖元素的equals方法),新生成的Stream中没有重复的元素

filter:

对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素

map:

对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。

flatMap:

和map类似,不同的是其每个元素转换得到的是Stream对象,会把子Stream中的元素压缩到父集合中

peek:

生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数;

limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素

skip: 返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream

中间的转换流可以不断的组合

List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10);

System.out.println(“sum is:”+nums.stream().filter(num -> num != null).

distinct().mapToInt(num -> num * 2).

peek(System.out::println).skip(2).limit(4).sum());

聚合

可变汇聚对应的只有一个方法:collect 将中间流的结果汇聚到一个容器里

Collector的工具类–[Collectors]:Collectors.toCollection()/Collectors.toList()/Collectors.toSet()

例如:collect(Collectors.toList());

其他汇聚 reduce方法:reduce方法非常的通用

ints.stream().reduce((sum, item) -> sum + item).get()

reduce方法接受一个函数,这个函数有两个参数,第一个参数是上次函数执行的返回值(也称为中间结果),第二个参数是stream中的元素,这个函数把这两个值相加,得到的和会被赋值给下次执行这个函数的第一个参数。

count方法:获取Stream中元素的个数

allMatch:是不是Stream中的所有元素都满足给定的匹配条件

anyMatch:Stream中是否存在任何一个元素满足匹配条件

noneMatch:是不是Stream中的所有元素都不满足给定的匹配条件

findFirst: 返回Stream中的第一个元素,如果Stream为空,返回空Optional

总结:

关于上述代码中说的Iterator和Stream结合使用的例子:

提供两个类:Student 和
@Data
@Getter
@Setter
public class Student {
    private String stuName;
    private int  stuAge;

    public Student(String stuName, int stuAge) {
        this.stuName = stuName;
        this.stuAge = stuAge;
    }

    public Student() {
    }
}

----------------------------------------------------------
@Data
@Getter
@Setter
public class User {
    private String  name;
    private int   age;
    private List<Student> stu; // 两个 类的关系

    public User(String name, int age, List<Student> stu) {
        this.name = name;
        this.age = age;
        this.stu = stu;
    }

    public User() {
    }

}
 Student stu1 = new Student("学生小刘", 22);
        Student stu2 = new Student("学生小张", 23);
        Student stu3 = new Student("学生小赵", 24);
        Student stu4 = new Student("学生小钱", 24);
        Student stu5 = new Student("学生小强", 24);
        //模拟后端数据库查出来的数据(学生和用户存在关联关系)
        ArrayList<Student> students = new ArrayList<>();
        students.add(stu1);
        students.add(stu2);
        students.add(stu3);
        students.add(stu4);
        User user = new User("张三", 55, students);
        //模拟前端传入的数据参数
        ArrayList<Student> uStudents = new ArrayList<>();
        uStudents.add(stu1);
        uStudents.add(stu3);
        uStudents.add(stu5);
        User user2 = new User("赵六", 57, uStudents);

        //假设后端采用的Spring Data 框架,继承了Hibenarate,实现更改集合元素可以自动更新中间表关系的
        //换言之就是我想实现  模拟数据库查出来的数据 中和前端传入的数据比对,多余的就删除掉;前端传进来后端查出来的数据中没有的,就添加

        //实现第一个需求:删除后端查出的数据中前端没传的
        Iterator<Student> it = user.getStu().iterator();
        while (it.hasNext()){
            Student next = it.next();
            if (user2.getStu().stream().noneMatch(item->next.getStuName().equals(item.getStuName()))) {
                //此处就是stream流和Iterator的结合使用 作为删除的条件使用
                it.remove();
            }
        }
        System.out.println(user);
//User(name=张三, age=55, stu=[Student(stuName=学生小刘, stuAge=22), Student(stuName=学生小赵, stuAge=24)])
//原先的stu2和stu3都没了,删掉了
        //实现第二个需求就是前端传了新的额元素去后端进行存储的
            // (都没进行对象的判空,目前还没掌握什么时候用Optional进行判空操作)
        for (Student student : user2.getStu()) {
            Optional<Student> first = user.getStu().stream().filter(item -> student.getStuName().equals(item.getStuName())).findFirst();
            if (first.isPresent()){
                continue;
            }
            user.getStu().add(student);
        }
        System.out.println(user);
//User(name=张三, age=55, stu=[Student(stuName=学生小刘, stuAge=22), Student(stuName=学生小赵, stuAge=24), Student(stuName=学生小强, stuAge=24)])
//将前端新传入的后端没存入的参数添加到集合中,

xxxmethod.save(user) //重新保存并更新中间表关系
    }

 Java 8 Optional 详细用法_旅行者-CSDN博客_optional用法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值