Java | List去重
今天在面试的时候说到了JavaList去重问题,随后查资料加做实验只做了如下表格(单位毫秒)。
100 | 1000 | 10000 | 100000 | 1000000 | |
---|---|---|---|---|---|
HashSet 去重 | 15 | 7 | 3 | 9 | 19 |
TreeSet去重 | 15 | 2 | 5 | 21 | 35 |
Stream(Java8新特性) | 183 | 0 | 1 | 9 | 12 |
双重for循环 | 2 | 27 | 64 | 3479 | 9533 |
for+contains方法 | 1 | 5 | 59 | 3467 | 9657 |
结论:有序使用TreeSet,无序使用HashSet
提到去重,那么大部分人首先想到的应该都是双重for循环,或者单层for循环+判断存在与否,然后赋值给一个新的List,但是这两种的效率较低,考虑到实际开发中,如果List中非重复元素过多,那么用户点击后相应操作后,可能会有秒级的等待(比如上表中随机数达到1000000级的时候,for循环可以达到10秒),因此最快速的响应给用户,就需要使用最高效的去重方式,因此可以考虑将List(允许存储重复数据)转换为Set(不允许存储重复数据)的方式,然后再转换为List并进行返回。
至于有序无序,则要考虑到,TreeSet底层使用的是TreeMap,本身有序,而HashSet采用的是HashMap,本身无序。
测试中用到的代码:
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Jim
* @Description List去重
* @createTime 2023年03月22日
*/
public class RemoveDuplication {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
List<Integer> list3 = new ArrayList<>();
List<Integer> list4 = new ArrayList<>();
List<Integer> list5 = new ArrayList<>();
Random random =new Random();
for (int i = 0; i < 100000; i++) {
int value =random.nextInt(100);
list1.add(value);
}
for (int i = 0; i < 100000; i++) {
int value =random.nextInt(1000);
list2.add(value);
}
for (int i = 0; i < 100000; i++) {
int value =random.nextInt(10000);
list3.add(value);
}
for (int i = 0; i < 100000; i++) {
int value =random.nextInt(100000);
list4.add(value);
}
for (int i = 0; i < 100000; i++) {
int value =random.nextInt(1000000);
list5.add(value);
}
long startTime ;
long endTime;
startTime = System.currentTimeMillis();
removeDuplicationByHashSet(list1);
endTime = System.currentTimeMillis();
System.out.println("使用HashSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByTreeSet(list1);
endTime = System.currentTimeMillis();
System.out.println("使用TreeSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByStream(list1);
endTime = System.currentTimeMillis();
System.out.println("使用java8新特性stream去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationBy2For(list1);
endTime = System.currentTimeMillis();
System.out.println("使用两个for循环实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByContains(list1);
endTime = System.currentTimeMillis();
System.out.println("使用List集合contains方法循环遍历:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByHashSet(list2);
endTime = System.currentTimeMillis();
System.out.println("使用HashSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByTreeSet(list2);
endTime = System.currentTimeMillis();
System.out.println("使用TreeSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByStream(list2);
endTime = System.currentTimeMillis();
System.out.println("使用java8新特性stream去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationBy2For(list2);
endTime = System.currentTimeMillis();
System.out.println("使用两个for循环实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByContains(list2);
endTime = System.currentTimeMillis();
System.out.println("使用List集合contains方法循环遍历:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByHashSet(list3);
endTime = System.currentTimeMillis();
System.out.println("使用HashSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByTreeSet(list3);
endTime = System.currentTimeMillis();
System.out.println("使用TreeSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByStream(list3);
endTime = System.currentTimeMillis();
System.out.println("使用java8新特性stream去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationBy2For(list3);
endTime = System.currentTimeMillis();
System.out.println("使用两个for循环实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByContains(list3);
endTime = System.currentTimeMillis();
System.out.println("使用List集合contains方法循环遍历:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByHashSet(list4);
endTime = System.currentTimeMillis();
System.out.println("使用HashSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByTreeSet(list4);
endTime = System.currentTimeMillis();
System.out.println("使用TreeSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByStream(list4);
endTime = System.currentTimeMillis();
System.out.println("使用java8新特性stream去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationBy2For(list4);
endTime = System.currentTimeMillis();
System.out.println("使用两个for循环实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByContains(list4);
endTime = System.currentTimeMillis();
System.out.println("使用List集合contains方法循环遍历:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByHashSet(list5);
endTime = System.currentTimeMillis();
System.out.println("使用HashSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByTreeSet(list5);
endTime = System.currentTimeMillis();
System.out.println("使用TreeSet实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByStream(list5);
endTime = System.currentTimeMillis();
System.out.println("使用java8新特性stream去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationBy2For(list5);
endTime = System.currentTimeMillis();
System.out.println("使用两个for循环实现List去重时间:"+(endTime-startTime)+"毫秒");
startTime = System.currentTimeMillis();
removeDuplicationByContains(list5);
endTime = System.currentTimeMillis();
System.out.println("使用List集合contains方法循环遍历:"+(endTime-startTime)+"毫秒");
}
public static List removeDuplicationBy2For(List<Integer> list) {
for (int i=0;i<list.size();i++)
{
for (int j=i+1;j<list.size();j++)
{
if(list.get(i).equals(list.get(j))){
list.remove(j);
}
}
}
return list;
}
public static List removeDuplicationByContains(List<Integer> list) {
List<Integer> newList =new ArrayList<>();
for (int i=0;i<list.size();i++)
{
boolean isContains =newList.contains(list.get(i));
if(!isContains){
newList.add(list.get(i));
}
}
list.clear();
list.addAll(newList);
return list;
}
public static List removeDuplicationByHashSet(List<Integer> list) {
HashSet<Integer> set = new HashSet<>(list);
//把List集合所有元素清空
list.clear();
//把HashSet对象添加至List集合
list.addAll(set);
return list;
}
public static List removeDuplicationByTreeSet(List<Integer> list) {
TreeSet<Integer> set = new TreeSet<>(list);
//把List集合所有元素清空
list.clear();
//把HashSet对象添加至List集合
list.addAll(set);
return list;
}
public static List removeDuplicationByStream(List<Integer> list) {
List<Integer> newList = list.stream().distinct().collect(Collectors.toList());
return newList;
}
}