详解Java去重题目及其解决方案”

去重题目:

"WZN", "567", "567", "100.0", "0", "0.0", "0", "0.0", "0", "null", "常规注册页面-专题书本-英语单词速记", "null", "DM", "89754"
"WZN", "538", "538", "100.0", "0", "0.0", "0", "0.0", "0", "null", "常规注册页面-专题书本-英语单词速记", "null", "DM", "89754"
"DB", "504", "504", "100.0", "0", "0.0", "0", "0.0", "0", "null", "互动项目-私人订制英语课程", "null", "BN", "93230"
"WZN", "485", "485", "100.0", "0", "0.0", "0", "0.0", "0", "null", "常规注册页面-专题书本-英语单词速记", "null", "DM", "89754"
"DB", "478", "471", "98.54", "0", "0.0", "0", "0.0", "0", "null", "互动项目-私人订制英语课程", "null", "BN", "93230"
"TCSC", "384", "371", "96.61", "0", "0.0", "0", "0.0", "0", "null", "互动项目-私人订制英语课程", "null", "BN", "92949"
"UnionPay", "356", "356", "100.0", "0", "0.0", "0", "0.0", "0", "null", "常规注册页面-专题书本-交际英语一本通", "null", "BN", "89544"
"DB", "307", "302", "98.37", "0", "0.0", "0", "0.0", "0", "null", "互动项目-私人订制英语课程", "null", "BN", "93230"
"DB", "302", "300", "99.34", "0", "0.0", "0", "0.0", "0", "null", "互动项目-私人订制英语课程", "null", "BN", "93230"
"UnionPay", "286", "286", "100.0", "0", "0.0", "0", "0.0", "0", "null", "常规注册页面-专题书本-交际英语一本通", "null", "BN", "89544"

需求:要求名字一样的合并成一条 并且每一列的数字要相加

一、什么是去重?

“去重即从一组数据中移除重复的元素,仅保留唯一的元素。在Java中,常用于集合类的数据处理,例如List、Set等。”

二、为什么需要去重?

“去重的主要目的是保证数据的一致性和唯一性,避免重复数据带来的冗余和资源浪费。在实际应用中,去重有很多场景,比如数据库处理中,同一数据不应重复插入,统计分析时需剔除重复项等。”

三、Java去重的常见方法

“在Java中,有多种方式可以实现去重。以下介绍几种常见方法。”

方法1 使用HashSet去重
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

public class RemoveDuplicates {
   public static void main(String[] args) {
       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(2);
       numbers.add(3);
       numbers.add(3);
       numbers.add(3);

       Set<Integer> uniqueNumbers = new HashSet<>(numbers);
       System.out.println("Unique numbers:" + uniqueNumbers);
   }
}

“使用HashSet是Java中去重较为简单和快速的一种方式。由于Set集合不允许有重复的元素,因此将List转换为Set可直接去重。”

方法2 使用Stream API去重
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

public class RemoveDuplicates {
   public static void main(String[] args) {
       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(2);
       numbers.add(3);
       numbers.add(3);
       numbers.add(3);

       List<Integer> uniqueNumbers = numbers.stream().distinct().collect(Collectors.toList());
       System.out.println("Unique numbers:" + uniqueNumbers);
   }
}

“在Java 8中,Stream API提供了更加简洁优雅的去重方式。通过distinct()方法可以实现去重操作。”

方法3 使用循环遍历手动去重
import java.util.List;
import java.util.ArrayList;

public class RemoveDuplicates {
   public static void main(String[] args) {
       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(2);
       numbers.add(3);
       numbers.add(3);
       numbers.add(3);

       List<Integer> uniqueNumbers = new ArrayList<>();
       for (Integer number :numbers) {
           if (!uniqueNumbers.contains(number)) {
               uniqueNumbers.add(number);
           }
       }
       System.out.println("Unique numbers:" + uniqueNumbers);
   }
}

“手动去重通过循环遍历,检查是否已存在于结果集中,若不存在则添加。虽然较为直观,但效率相对较低。”

四、去重策略的性能比较

“对于不同的去重方法,在不同情况下可能会有不同的性能表现。以下是对常见去重方法的简单性能分析。”

1.HashSet去重:基于哈希表实现,时间复杂度为O(1),适用场景广泛。

2.Stream API去重:简洁优雅,适合现代Java代码风格,性能与HashSet相近。

3.手动遍历去重:时间复杂度为O(n^2),适用于小数据量的去重操作,性能较差。

五、解决需求:要求名字一样的合并成一条 并且每一列的数字要相加
代码实现:
/**
 * 要求名字一样的合并成一条 并且每一列的数字要相加
 */
public class duplicateRemoval {
    public static void main(String[] args) {

        // 设置编码(仅在需要时启用)
//       try {
//           System.setOut(new java.io.PrintStream(System.out,true,"UTF-8"));
//       } catch (java.io.UnsupportedEncodingException e) {
//           System.err.println("无法设置UTF-8编码:" + e.getMessage());
//       }

        // 原始数据,以字符串数组列表的形式给出
        List<String[]> data = Arrays.asList(
                new String[]{"WZN","567","567","100.0","0","0.0","0","0.0","0","null","常规注册页面-专题书本-英语单词速记","null","DM","89754"},
                new String[]{"WZN","538","538","100.0","0","0.0","0","0.0","0","null","常规注册页面-专题书本-英语单词速记","null","DM","89754"},
                new String[]{"DB","504","504","100.0","0","0.0","0","0.0","0","null","互动项目-私人订制英语课程","null","BN","93230"},
                new String[]{"WZN","485","485","100.0","0","0.0","0","0.0","0","null","常规注册页面-专题书本-英语单词速记","null","DM","89754"},
                new String[]{"DB","478","471","98.54","0","0.0","0","0.0","0","null","互动项目-私人订制英语课程","null","BN","93230"},
                new String[]{"TCSC","384","371","96.61","0","0.0","0","0.0","0","null","互动项目-私人订制英语课程","null","BN","92949"},
                new String[]{"UnionPay","356","356","100.0","0","0.0","0","0.0","0","null","常规注册页面-专题书本-交际英语一本通","null","BN","89544"},
                new String[]{"DB","307","302","98.37","0","0.0","0","0.0","0","null","互动项目-私人订制英语课程","null","BN","93230"},
                new String[]{"DB","302","300","99.34","0","0.0","0","0.0","0","null","互动项目-私人订制英语课程","null","BN","93230"},
                new String[]{"UnionPay","286","286","100.0","0","0.0","0","0.0","0","null","常规注册页面-专题书本-交际英语一本通","null","BN","89544"}
        );

        // 使用Map来合并记录,其中键是名字,值是一个列表,包含所有具有该名字的记录的其余部分
        Map<String,List<String[]>> mergedRecords = new HashMap<>();

        // 遍历原始数据,将记录合并到Map中
        for (String[] record :data) {
            String name = record[0];
            List<String[]> recordsForName = mergedRecords.getOrDefault(name,new ArrayList<>());
            recordsForName.add(record);
            mergedRecords.put(name,recordsForName);
        }

        // 现在,mergedRecords包含了按名字分组的记录列表。我们需要进一步处理这些列表,以合并数字列。

        // 创建一个新的列表来存储合并后的记录
        List<String[]> mergedData = new ArrayList<>();

        // 遍历Map,合并记录
        //mergedRecords.entrySet() 是 Java 中 Map 接口提供的一个方法
        // 它返回 Map 中所包含的所有映射的 Set 视图
        // 其中每个元素都是一个键值对(Key-Value Pair)
        // 在 Java 中这个键值对是通过 Map.Entry 接口来表示的。
        //
        //当调用 mergedRecords.entrySet() 时
        // 你得到的是一个 Set<Map.Entry<String, List<String[]>>> 类型的对象
        // 这个集合中的每个元素都是一个 Map.Entry 对象
        // 它代表 mergedRecords Map 中的一个键值对
        // 在这个例子中,键(Key)是 String 类型的名字(name)
        // 而值(Value)是一个 List<String[]> 类型的列表
        // 列表中包含的是与这个名字相关联的所有记录(每个记录都是一个 String[] 类型的数组)
        for (Map.Entry<String,List<String[]>> entry :mergedRecords.entrySet()) {
            String name = entry.getKey();
            List<String[]> records = entry.getValue();

            // 初始化了一个名为mergedRecord的字符串数组
            // 其长度与records列表中的第一个记录的字段数相同
            // 这个数组将用于存储合并后的记录
            String[] mergedRecord = new String[records.get(0).length];
            // 假设name是一个已经定义好的字符串变量
            // 表示合并后记录的第一个字段(比如一个名字)
            // 这行代码将name赋值给mergedRecord的第一个元
            mergedRecord[0] = name;

            // 遍历记录的其余部分,对数字列进行累加
            //循环遍历mergedRecord数组(除了第一个元素,因为第一个元素已经被设置为名字)
            // 用于处理剩余的字段
            for (int i = 1;i < mergedRecord.length;i++) {
                //在循环内部
                // 初始化两个变量:sum用于累加数字字段的值,isNumeric用于标记当前字段是否为数字字段(默认为true)
                double sum = 0;
                boolean isNumeric = true;

                for (String[] record :records) {
                    try {
                        sum += Double.parseDouble(record[i]);// 尝试将该列值转换为double
                    } catch (NumberFormatException e) {
                        // 捕获到异常时,说明此列为非数值,保持原样
                        isNumeric = false;
                        break;
                    }
                }

                //如果isNumeric为true,则将累加的结果(sum)转换为字符串并赋值给mergedRecord的当前字段。
                // 如果isNumeric为false,则将该字段设置为records列表中第一个记录的相应字段的值
                if (isNumeric) {
                    mergedRecord[i] = String.valueOf(sum);// 将累加结果转换回字符串
                } else {
                    mergedRecord[i] = records.get(0)[i];// 保持第一个记录的非数值字段
                }
            }

            // 将合并后的记录添加到结果列表中
            mergedData.add(mergedRecord);
        }

        // 控制台输出合并后的数据结果
        for (String[] record :mergedData) {
            System.out.println(Arrays.toString(record));
        }
    }
}
控制层输出:

六、总结

“通过本文的讲解,可以看到在Java中实现数据去重的方法多种多样。选择合适的方法不仅可以提高代码的可读性,还能优化性能。希望大家在实际项目中灵活运用这些去重策略,提升开发效率和体验。”

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值