0
点赞
收藏
分享

微信扫一扫

java stream 某个字段去重排序

一:概述

在这个博客文章中,我们将探讨如何使用Java Stream API对某个字段的去重和排序进行操作。我们将介绍几种不同的方法,每种方法都会有一个实际的案例来展示如何实现。

二:具体说明

<1>Collectors.toCollection()

第一种方法是使用Collectors.toCollection()方法来指定一个自定义的集合类型,例如TreeSet,它可以帮助我们自动去重和排序。

案例:

假设我们有一个学生列表,每个学生有学号和姓名两个字段,我们想要根据学号进行去重和排序。 

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
                new Student("张三", "001"),
                new Student("李四", "002"),
                new Student("王五", "001"),
                new Student("赵六", "003")
        );

        List<String> distinctStudentIds = students.stream()
                .collect(Collectors.toCollection(TreeSet::new))
                .stream()
                .map(Student::getStudentId)
                .collect(Collectors.toList());

        System.out.println(distinctStudentIds);
    }

    public static class Student {
        private String name;
        private String studentId;

        public Student(String name, String studentId) {
            this.name = name;
            this.studentId = studentId;
        }

        public String getName() {
            return name;
        }

        public String getStudentId() {
            return studentId;
        }
    }
}

在这个案例中,我们首先使用Collectors.toCollection(TreeSet::new)方法将学生列表转换为一个去重的TreeSet集合。然后,我们再次调用stream()方法来获取去重后的学生列表,并通过map()方法提取出学号。最后,我们使用collect()方法将结果转换为列表。

<2>Collectors.collectingAndThen()

第二种方法是使用Collectors.collectingAndThen()方法来指定一个自定义的收集器。这种方法更加灵活,可以让我们在收集结果之前执行一些额外的操作。

案例:

假设我们有一个商品列表,每个商品有名称和价格两个字段,我们想要根据名称进行去重,并根据价格进行排序。

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
                new Product("电视", 2000),
                new Product("冰箱", 3000),
                new Product("电视", 1500),
                new Product("洗衣机", 1800)
        );

        List<Product> distinctAndSortedProducts = products.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(TreeSet::new),
                        list -> {
                            list.forEach(product -> {
                                product.setPrice(product.getPrice());
                            });
                            return list;
                        }
                ))
                .stream()
                .collect(Collectors.toList());

        System.out.println(distinctAndSortedProducts);
    }

    public static class Product {
        private String name;
        private double price;

        public Product(String name, double price) {
            this.name = name;
            this.price = price;
        }

        public String getName() {
            return name;
        }

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

        public double getPrice() {
            return price;
        }

        public void setPrice(double price) {
            this.price = price;
        }
    }
}

在这个案例中,我们首先使用Collectors.toCollection(TreeSet::new)方法将商品列表转换为一个去重的TreeSet,然后对这个TreeSet进行额外的操作。在这个案例中,我们想要在去重后对每个商品的价格进行排序。

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
                new Product("电视", 2000),
                new Product("冰箱", 3000),
                new Product("电视", 1500),
                new Product("洗衣机", 1800)
        );

        List<Product> distinctAndSortedProducts = products.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(TreeSet::new),
                        productsTreeSet -> {
                            productsTreeSet.forEach(product -> {
                                product.setPrice(product.getPrice());
                            });
                            return productsTreeSet;
                        }
                ))
                .stream()
                .collect(Collectors.toList());

        System.out.println(distinctAndSortedProducts);
    }

    public static class Product {
        private String name;
        private double price;

        public Product(String name, double price) {
            this.name = name;
            this.price = price;
        }

        public String getName() {
            return name;
        }

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

        public double getPrice() {
            return price;
        }

        public void setPrice(double price) {
            this.price = price;
        }
    }
}

在这个代码中,collectingAndThen接受两个参数:一个收集器和一个函数。第一个参数(收集器)负责去重和建立一个TreeSet,第二个参数(函数)则负责对TreeSet中的元素进行额外的操作。在这个例子中,我们没有实际改变TreeSet中的元素,但是通过调用setPrice方法,我们确保了每个产品的价格都被访问并保留了原来的值。然后,我们再次将TreeSet转换为列表。

<3>Collectors.toMap()

第三种方法是使用Collectors.toMap()来创建一个映射(Map),其中键是我们要去重的字段,值是原始对象。这种方法允许我们以键值对的形式去重,并且可以自定义键的生成方式。

案例:

假设我们有一个员工列表,每个员工有一个ID和一个姓名,我们想要根据ID去重并排序。 

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
                new Employee("Alice", 1),
                new Employee("Bob", 2),
                new Employee("Alice", 1),
                new Employee("Charlie", 3)
        );

        List<Employee> distinctAndSortedEmployees = employees.stream()
                .collect(Collectors.toMap(
                        Employee::getId,
                        Function.identity(),
                        (existing, replacement) -> existing
                ))
                .values()
                .stream()
                .collect(Collectors.toList());

        System.out.println(distinctAndSortedEmployees);
    }

    public static class Employee {
        private String name;
        private int id;

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

        public String getName() {
            return name;
        }

        public int getId() {
            return id;
        }
    }
}

在这个案例中,我们使用Collectors.toMap()来创建一个以员工ID为键的映射。这里我们使用了三个参数的toMap方法,第一个参数是键的映射函数,第二个参数是值的映射函数,第三个参数是当键已经存在时如何处理新值的方法。在这个例子中,我们使用Function.identity()作为值的映射函数,因为我们需要保留原始的员工对象。当键已经存在时,我们选择保留现有的值((existing, replacement) -&gt; existing)。最后,我们通过调用values()方法来获取映射中的值,并将其转换为列表。

<4>Collectors.groupingBy()

第四种方法是使用Collectors.groupingBy()来对流中的元素进行分组,然后从分组中提取出需要的字段。这种方法适用于复杂的数据结构,可以在分组后对每个组执行去重和排序的操作。

案例:

假设我们有一个订单列表,每个订单有一个商品ID和一个数量,我们想要根据商品ID去重并排序每个商品的总数量。

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Order> orders = Arrays.asList(
                new Order("TV", 2),
                new Order("Fridge", 1),
                new Order("TV", 1),
                new Order("Washing Machine", 3)
        );

        Map<String, Long> productToTotalQuantity = orders.stream()
                .collect(Collectors.groupingBy(
                        Order::getProductId,
                        Collectors.summingLong(Order::getQuantity)
                ))
                .entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        Long::sum
                ));

        productToTotalQuantity.forEach((productId, totalQuantity) ->
                System.out.println(productId + " : " + totalQuantity));
    }

    public static class Order {
        private String productId;
        private int quantity;

        public Order(String productId, int quantity) {
            this.productId = productId;
            this.quantity = quantity;
        }

        public String getProductId() {
            return productId;
        }

        public int getQuantity() {
            return quantity;
        }
    }
}

在这个案例中,我们首先使用groupingBy对订单按照商品ID进行分组,然后使用summingLong来计算每个分组中订单的数量总和。接着,我们再次使用entrySet().stream()将分组转换为映射项的流,然后使用toMap来将分组和数量总和转换为一个不重复的映射。在这个映射中,我们通过Long::sum来处理相同商品ID的分组数量总和。

<5>总结

在本博客文章中,我们探讨了四种使用Java Stream API对某个字段进行去重和排序的方法。每种方法都有对应的实际案例来展示如何实现。Collectors.toCollection()方法简单直接,适用于基本数据类型;Collectors.collectingAndThen()方法更加灵活,可以在去重后对元素进行自定义操作;Collectors.toMap()方法适用于需要以键值对形式去重的情况;而Collectors.groupingBy()方法则适用于更复杂的数据结构,可以在分组后对每个组执行去重和排序的操作。根据不同的需求,我们可以选择合适的方法来实现去重和排序。

java stream 某个字段去重排序_java

举报

相关推荐

0 条评论