需求:

现在我有一个用户集合,集合中的各个用户的电话号码可能会重复,电话号码重复的用户只需要保留一个即可。

用户实体:

package com.javabasic.javabasic.workidea;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    private Long id;

    /**
     * 手机号码
     */
    private String phone;

    /**
     * 密码,加密存储
     */
    private String password;

    /**
     * 昵称,默认是随机字符
     */
    private String nickName;

    /**
     * 用户头像
     */
    private String icon = "";

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;


}

解决方案:

直接上代码

no bb ,show me your code

package com.javabasic.javabasic.workidea;

import cn.hutool.core.util.StrUtil;

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

/**
 * @Author: Ambation
 * @Description:
 * @Date Created in 2023-11-16-21:39
 * @Modified By:
 */
public class TestDeWeight {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId((long) i);
            user.setPhone("13412345678");
            user.setPassword("qwer" + i);
            user.setNickName("小米" + i);
            userList.add(user);
        }
        /**
         * 要求根据phone字段进行去重
         */
        //方法一: 使用集合双重循环进行去重
        for (int i = 0; i < userList.size(); i++) {
            for (int j = i + 1; j < userList.size(); j++) {
                if (userList.get(i).getPhone().equals(userList.get(j).getPhone())) {
                    userList.remove(j);
                    j--;
                }
            }
        }
        System.out.println(userList);
        //方法二: 使用集合的hashSet进行去重
        HashSet<String> hashSet = new HashSet<>();
        //遍历集合,将phone去重放入hashSet
        for (User user : userList) {
            String phone = user.getPhone();
            if (phone != null && !phone.isEmpty()) {
                hashSet.add(phone);
            }
        }
        //遍历用户集合,如果phone在hashSet中,则将该用户添加到新建的集合中
        ArrayList<User> distictUserList = new ArrayList<>();
        for (String phone : hashSet) {
            for (User user : userList) {
                String phoneu = user.getPhone();
                if (phoneu != null && !phoneu.isEmpty()) {
                    if (phone.equals(phoneu)) {
                        distictUserList.add(user);
                        break;
                    }
                }
            }
        }
        System.out.println(distictUserList);
        //方法三: stream流进行去重
        userList.stream().collect(
                () -> new HashSet<>(),
                (hashSet1, user) -> {
                    String phone = user.getPhone();
                    if (phone != null && !phone.isEmpty()) {
                        hashSet1.add(phone);
                    }
                },
                (hashSet1, hashSet2) -> {
                    hashSet1.addAll(hashSet2);
                }
        );
        System.out.println(userList);

        //方法四:stream流分组进行去重
        ArrayList<User> distictUserLists = new ArrayList<>();
        Map<String, List<User>> groupByPhone = userList.stream().filter(u -> StrUtil.isNotBlank(u.getPhone()))
                .collect(Collectors.groupingBy(User::getPhone));
        groupByPhone.forEach((k, v) -> {
            distictUserLists.add(v.get(0));
        });

        System.out.println(distictUserLists);


        //=====================ChatGTP推荐的方案=====================

        //方法五: 自定义对象进行去重,比较器实现
        Set<User> set = new TreeSet<>(new MyObjectComparator());
        // 将需要去重的对象添加到set中
        set.addAll(userList);
        System.out.println(set);

        //方法六: 使用stream流进行去重
        /**
         * 在这个示例中,我们通过stream将原始列表转换为流,
         * 然后使用Collectors.toMap方法以Phone字段作为键进行收集。
         * 在这个过程中,我们使用了一个合并函数(existing, replacement) -> existing
         * 来指定如果遇到重复的键时保留已存在的值。
         * 最后,我们取出map的值部分,并再次使用collect方法转换为列表,
         * 得到了根据Phone字段去重后的列表。
         */
        List<User> uniqueObjects = userList.stream()
                .collect(Collectors.toMap(User::getPhone, obj -> obj, (existing, replacement) -> existing))
                .values()
                .stream()
                .collect(Collectors.toList());

        System.out.println(uniqueObjects);
        
        //=====================文心一言 推荐的方案=====================

        //方法七: 使用map进行去重
        Map<String, User> phoneUserMap = new HashMap<>();
        for (User user : userList) {
            if (!phoneUserMap.containsKey(user.getPhone())) {
                phoneUserMap.put(user.getPhone(), user);
            }
        }

        // Print out the unique users
        for (User user : phoneUserMap.values()) {
            System.out.println(user);
        }

        //方法八: 使用stream流进行去重
        List<User> uniqueUserList = userList.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getPhone))),
                        ArrayList::new));

        // Print out the unique users
        uniqueUserList.forEach(System.out::println);
    }

}

class MyObjectComparator implements Comparator<User> {
    @Override
    public int compare(User o1, User o2) {
        return o1.getPhone().compareTo(o2.getPhone());
    }
}

总结:

自己想起来的实现方案会有些复杂,不得不说chatGTP确实很厉害,直接把这个问题的最优代码给你,完全无需优化。文心一言要差一些,你需要问它,还有什么更好的解决方案吗?它才会给你最优方案。


思考:

人工智能给的方案确实很好,但是它给你的代码,你真的能看的明白,并理解吗?现在的各种模型,把你的需求讲给它,10秒钟,它就会生成一段无需优化的最优代码,很快很准。如果我们提前经过思考,想过很多方法,却不知如何实现,一问人工智能,它给的方案会让你醍醐灌顶,那种感觉很爽很爽。


多思考,多尝试。


尾声:

大家有什么好的去重方案,欢迎讨论。