java8 集合操作功能

发布时间 2023-10-31 10:59:45作者: 黄橙

Java 8引入了许多新的集合操作功能,包括但不限于以下几项:

  1. forEach:使用Lambda表达式遍历集合中的每个元素。
  2. stream:将集合转换为流,以便进行各种操作,如过滤、映射、排序等。
  3. filter:根据指定的条件过滤集合中的元素,并返回过滤后的结果。
  4. map:将集合中的每个元素映射为另一个元素,并返回映射后的结果。
  5. reduce:将集合中的元素进行累积运算,得到一个最终结果。
  6. collect:将流中的元素收集到一个集合中,可以指定收集的类型。
  7. sorted:对集合中的元素进行排序。
  8. distinct:去除集合中重复的元素。
  9. limit:限制集合中元素的数量。
  10. skip:跳过集合中指定数量的元素。
  11. anyMatch:判断集合中是否存在满足指定条件的元素。
  12. allMatch:判断集合中的所有元素是否都满足指定条件。
  13. noneMatch:判断集合中是否不存在满足指定条件的元素。
  14. count:统计集合中元素的数量。
  15. max:获取集合中的最大元素。
  16. min:获取集合中的最小元素。

这些功能使得对集合进行各种操作变得更加简洁和灵活,提高了代码的可读性和可维护性。

 

 

public class Employee {

    private int id;
    private String name;
    private int age;
    private double salary;
    private Status status;

    public Employee() {
    }

    public Employee(String name) {
        this.name = name;
    }

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Employee(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public Employee(int id, String name, int age, double salary, Status status) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String show() {
        return "测试方法引用!";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(salary);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (age != other.age)
            return false;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return Double.doubleToLongBits(salary) == Double.doubleToLongBits(other.salary);
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status
                + "]";
    }

    public enum Status {
        FREE, BUSY, VOCATION
    }

}
import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestStreamAPI3 {
    static List<Employee> emps = Arrays.asList(new Employee(102, "李四", 79, 6666.66, Status.BUSY), new Employee(101, "张三", 18, 9999.99, Status.FREE), new Employee(103, "王五", 28, 3333.33, Status.VOCATION), new Employee(104, "赵六", 8, 7777.77, Status.BUSY), new Employee(104, "赵六", 8, 7777.77, Status.FREE), new Employee(104, "赵六", 8, 7777.77, Status.FREE), new Employee(105, "田七", 38, 5555.55, Status.BUSY));
    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();
        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }

    //3. 终止操作
    /* reduce 是一个流操作方法,用于将流中的元素按照指定的操作进行归约(reduce)操作,最终得到一个结果。
        归约
        reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
     */
    @Test
    public void test1(){
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(sum);
// 求最大值
        Optional<Integer> max = list.stream().reduce(Integer::max);
        max.ifPresent(System.out::println); // 输出: 5

// 求乘积
        Optional<Integer> product = list.stream().reduce((a, b) -> a * b);
        product.ifPresent(System.out::println); // 输出: 120
        System.out.println("----------------------------------------");
        Optional<Double> op = emps.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(op.get());
        Optional<Double> op1 = emps.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(op1.get());
    }
    //需求:搜索名字中 “六” 出现的次数
    @Test
    public void test2(){
        Optional<Integer> sum = emps.stream()
                .map(Employee::getName)
                .flatMap(TestStreamAPI3::filterCharacter)
                .map((ch) -> {
                    if(ch.equals("六"))
                        return 1;
                    else
                        return 0;
                }).reduce(Integer::sum);

        System.out.println(sum.get());
    }
    private static void filter() {
        List<Employee> list = Arrays.asList(new Employee(102, "李四", 79, 6666.66, Status.BUSY), new Employee(101, "张三", 18, 9999.99, Status.FREE), new Employee(103, "王五", 28, 3333.33, Status.VOCATION), new Employee(104, "赵六", 8, 7777.77, Status.BUSY), new Employee(105, "赵六2", 5, 7777.77, Status.FREE), new Employee(106, "赵六3", 8, 7777.77, Status.FREE), new Employee(107, "田七", 38, 5555.55, Status.BUSY));
        List<Employee> list2 = list.stream().filter(u -> Objects.equals(u.getAge(), 8)).collect(Collectors.toList());
        list2.forEach(System.out::println);
        List<String> list3 = list.stream().filter(u -> Objects.equals(u.getAge(), 8)).map(Employee::getName).collect(Collectors.toList());
        list3.forEach(System.out::println);
        List<Employee> list4 = list.stream().filter(u -> u.getAge() == 8).collect(Collectors.toList());
        list4.forEach(System.out::println);

        System.out.println("--------------------------");
        List<Emp> list5 = list.stream().filter(u -> u.getAge() == 8).map(u -> {
            Emp exportVo = new Emp();
            exportVo.setId(u.getId());
            exportVo.setAge(u.getAge());
            return exportVo;
        }).collect(Collectors.toList());

        list5.forEach(System.out::println);
        System.out.println("--------------------------");
        List<Emp> list6 = list.stream().map(u -> {
            Emp exportVo = new Emp();
            exportVo.setId(u.getId());
            exportVo.setAge(u.getAge());
            return exportVo;
        }).collect(Collectors.toList());
        list6.forEach(System.out::println);
    }
    /**
     * anyMatch():匹配到任何一个元素和指定的元素相等,返回 true
     * 1、多元素取反,任何一个元素不等于 a 的返回 true
     * 2、单元素取反,因为是单元素只有a,没有不等于 a 的元素,所以不成立返回 false
     */
    private static void anyMatch() {
//1、正常匹配,多元素
        List<String> strList = ListUtil.toList("a", "b", "c", "d");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList).stream().anyMatch(obj -> obj.equals("a"));
        System.out.println("anyMatch()测试多元素结果:" + a);

        List<Employee> list = Arrays.asList(new Employee(102, "李四", 79, 6666.66, Status.BUSY), new Employee(101, "张三", 18, 9999.99, Status.FREE), new Employee(103, "王五", 28, 3333.33, Status.VOCATION), new Employee(104, "赵六", 8, 7777.77, Status.BUSY), new Employee(105, "赵六2", 5, 7777.77, Status.FREE), new Employee(106, "赵六3", 8, 7777.77, Status.FREE), new Employee(107, "田七", 38, 5555.55, Status.BUSY));

        boolean e = list.stream().anyMatch(obj -> Objects.equals(obj.getName(), "李四"));
        System.out.println("anyMatch()测试多元素结果:" + e);
        //    2、正常匹配,单元素

        List<String> strList2 = ListUtil.toList("a");
        boolean b = Optional.ofNullable(strList2).orElseGet(ListUtil::toList).stream().anyMatch(obj -> obj.equals("a"));
        System.out.println("anyMatch()测试单元素结果:" + b);
        //1、无论多元素还是单元素,只要匹配到任何一个元素等于 a 的都返回 true
        //3、取反匹配,多元素
        List<String> strList3 = ListUtil.toList("a", "b", "c", "d");
        boolean c = Optional.ofNullable(strList3).orElseGet(ListUtil::toList).stream().anyMatch(obj -> !obj.equals("a"));
        System.out.println("anyMatch()测试取反多元素结果:" + c);
        //4、取反匹配,单元素
        List<String> strList4 = ListUtil.toList("a");
        boolean d = Optional.ofNullable(strList4).orElseGet(ListUtil::toList).stream().anyMatch(obj -> !obj.equals("a"));
        System.out.println("anyMatch()测试取反单元素结果:" + d);
    }

    /**
     * allMatch():匹配到全部元素和指定的元素相等,返回 true
     * 1、allMatch() 所有元素都等于指定元素返回 true
     * 2、allMatch() 如果取反,等效于 noneMatch() 所有元素不等于指定元素返回 true
     */
    private static void allMatch() {
        //1、匹配多元素
        List<String> strList = ListUtil.toList("a", "b", "c", "d");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList).stream().allMatch(obj -> obj.equals("a"));
        System.out.println("allMatch()测试多元素结果:" + a);
        //2、匹配单元素
        List<String> strList2 = ListUtil.toList("a");
        boolean b = Optional.ofNullable(strList2).orElseGet(ListUtil::toList).stream().allMatch(obj -> obj.equals("a"));
        System.out.println("allMatch()测试单元素结果:" + b);
        List<String> strList1 =   Optional.ofNullable(strList).orElseGet(ListUtil::toList);
        System.out.println(strList1);
        System.out.println("**********************");
        List<String> list1 = ListUtil.toList("a", "b", "c", "d");
        List<String> list2 = ListUtil.toList( "b",  "d");
        boolean b1=  list1.stream().noneMatch(obj -> obj.equals("a"));
        System.out.println(b1);
        System.out.println("$$$$$$$$$$$$$$$");
        List<String>     lastResult3 = list1.stream()
                .filter(add -> list2.stream()
                        .anyMatch(all ->  Objects.equals(add, all)
                        ) ).collect(Collectors.toList());
        System.out.println(lastResult3);
        System.out.println(b1);
        System.out.println("-----------");
        boolean b2= list1.stream()
                .allMatch(add -> list2.stream()
                        .anyMatch(all ->  Objects.equals(add, all)
                        ) );
        System.out.println(b2);
        boolean b3= list2.stream()
                .allMatch(add -> list1.stream()
                        .anyMatch(all ->  Objects.equals(add, all)
                        ) );
        System.out.println(b3);
    }

    /**
     * noneMatch():与 allMatch() 效果相反
     * 1、noneMatch()所有元素都不等于指定元素返回 true
     * 2、noneMatch() 如果取反,等效于 allMatch() 所有元素等于指定元素返回 true
     */
    private static void noneMatch() {
        //1、匹配多元素
        List<String> strList = ListUtil.toList("b", "c", "d");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList).stream().noneMatch(obj -> obj.equals("a"));
        System.out.println("noneMatch()测试多元素结果:" + a);
        //2、匹配单元素
        List<String> strList2 = ListUtil.toList("a");
        boolean b = Optional.ofNullable(strList2).orElseGet(ListUtil::toList).stream().noneMatch(obj -> obj.equals("a"));
        System.out.println("noneMatch()测试单元素结果:" + b);
    }

    /**
     * reduce 是一个流操作方法,用于将流中的元素按照指定的操作进行归约(reduce)操作,最终得到一个结果。     *
     * reduce 方法有三种重载形式:
     */
    public static void reduce() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer sum = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println(sum);
        // 求最大值
        Optional<Integer> max = list.stream().reduce(Integer::max);
        max.ifPresent(System.out::println); // 输出: 5
        // 求乘积
        Optional<Integer> product = list.stream().reduce((a, b) -> a * b);
        product.ifPresent(System.out::println); // 输出: 120
        Optional<Double> op = emps.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(op.get());
    }
    //collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
    @Test
    public void test3() {
        List<String> list = emps.stream().map(Employee::getName).collect(Collectors.toList());
        list.forEach(System.out::println);
        System.out.println("----------------------------------");
        Set<String> set = emps.stream().map(Employee::getName).collect(Collectors.toSet());
        set.forEach(System.out::println);
        System.out.println("----------------------------------");
        HashSet<String> hs = emps.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
        hs.forEach(System.out::println);
    }
    @Test
    public void test4() {
        Optional<Double> max = emps.stream().map(Employee::getSalary).collect(Collectors.maxBy(Double::compare));
        System.out.println(max.get());
        Optional<Employee> op1 = emps.stream().collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        Optional<Employee> op = emps.stream().min(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(op.get());
        Double sum = emps.stream().collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);
        Double avg = emps.stream().collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);
        Long count = emps.stream().collect(Collectors.counting());
        System.out.println(count);
        System.out.println("--------------------------------------------");
        DoubleSummaryStatistics dss = emps.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(dss.getMax());
    }
    //分组
    @Test
    public void test5() {
        Map<Status, List<Employee>> map = emps.stream().collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(map);
    }
    //多级分组
    @Test
    public void test6() {
        Map<Status, Map<String, List<Employee>>> map = emps.stream().collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
            if (e.getAge() >= 60) return "老年";
            else if (e.getAge() >= 35) return "中年";
            else return "成年";
        })));
        System.out.println(map);
        System.out.println(JSON.toJSONString(map));
    }
    //分区
    @Test
    public void test7() {
        Map<Boolean, List<Employee>> map = emps.stream().collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000));
        System.out.println(map);
    }
    
    @Test
    public void test8() {
        String str = emps.stream().map(Employee::getName).collect(Collectors.joining(",", "----", "----"));
        System.out.println(str);
        String str1 = emps.stream().map(Employee::getName).collect(Collectors.joining(","));
        System.out.println(str1);
        String str2 = emps.stream().map(Employee::getName).collect(Collectors.joining(",", "[", "]"));
        System.out.println(str2);
    }

    @Test
    public void test9() {
        Optional<Double> sum = emps.stream().map(Employee::getSalary).collect(Collectors.reducing(Double::sum));
        System.out.println(sum.get());
    }

    @Test
    public void test10() {
        //根据device_code去重,取出重复值
        List<String> dupList = emps.stream().collect(Collectors.groupingBy(Employee::getName, Collectors.counting())).entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());
        System.out.println(dupList);
    }

    @Test
    public void test11() {
        //字符串取出重复值
        List<String> list = new ArrayList<>();
        List<String> repeatList = list.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting())).entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());
    }
    //@Test
    public static void test12(){
        // 需要过滤的集合
        List<Employee> first = Arrays.asList(
                new Employee(102, "李四", 79, 6666.66, Status.BUSY),
                new Employee(101, "张三", 18, 9999.99, Status.FREE),
                new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
                //new Employee(104, "赵六", 8, 7777.77, Status.BUSY),
                //new Employee(105, "赵六", 8, 7777.77, Status.FREE),
                new Employee(106, "赵六", 8, 7777.77, Status.FREE),
                new Employee(107, "田七", 38, 5555.55, Status.BUSY)
        );
        // 参照集合
        List<Employee> second = Arrays.asList(
                new Employee(102, "李四", 79, 6666.66, Status.BUSY),
                new Employee(1056, "赵六", 8, 7777.77, Status.FREE),
                new Employee(1056, "赵六1", 8, 7777.77, Status.FREE),
                new Employee(1069, "田七", 38, 5555.55, Status.BUSY)
        );
        System.out.println(1);
        first.forEach(System.out::println);
        System.out.println(2);
        second.forEach(System.out::println);
    /*    List<Employee> lastResult = first.stream()
                .filter(add -> second.stream()
                        .noneMatch(all -> Objects.equals(add.getId(), all.getId())&&   Objects.equals(add.getAge(), all.getAge()) ) ).collect(Collectors.toList());
*/
        // noneMatch:判断集合中是否不存在满足指定条件的元素。
        List<Employee>       lastResult1 = first.stream()
                .filter(add -> second.stream()
                        .noneMatch(all ->  Objects.equals(add.getName(), all.getName()) ) ).collect(Collectors.toList());
        System.out.println(1);
        lastResult1.forEach(System.out::println);
        //allMatch:判断集合中的所有元素是否都满足指定条件。
        List<Employee>     lastResult2 = first.stream()
                .filter(add -> second.stream()
                        .allMatch(all ->  Objects.equals(add.getId(), all.getId())
                        ) ).collect(Collectors.toList());
        System.out.println(2);
        lastResult2.forEach(System.out::println);
        //anyMatch:判断集合中是否存在满足指定条件的元素。
        List<Employee>     lastResult3 = first.stream()
                .filter(add -> second.stream()
                        .anyMatch(all ->  Objects.equals(add.getId(), all.getId())
                        ) ).collect(Collectors.toList());
        System.out.println(3);
        lastResult3.forEach(System.out::println);
        List<Employee>         lastResult4 = first.stream()
                .filter(add -> second.stream()
                        .anyMatch(all ->  Objects.equals(add.getName(), all.getName()) ) ).collect(Collectors.toList());
        System.out.println(4);
        lastResult4.forEach(System.out::println);
        System.out.println(5);
        List<Employee>         lastResult5 = first.stream()
                .filter(add -> second.stream()
                        .anyMatch(all ->  {
                            return    (Objects.equals(add.getName(), all.getName())) || (add.getName() != null && add.getName().equals( all.getName()));
                            //return Objects.equals(add.getName(), all.getName());
                        }) ).collect(Collectors.toList());

        lastResult5.forEach(System.out::println);
        BiFunction<String,Integer,Employee> fn2 = Employee::new;
        Stream<Employee> stream01 = Stream.of(fn2.apply("刘德华", 58), fn2.apply("张学友", 56), fn2.apply("郭富城", 54), fn2.apply("黎明", 52));
    }

    public static void main(String[] args) {
        test12();
    }
}