去重题目:
"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中实现数据去重的方法多种多样。选择合适的方法不仅可以提高代码的可读性,还能优化性能。希望大家在实际项目中灵活运用这些去重策略,提升开发效率和体验。”