List数组高效率去重
一、环境准备–生成包含重复元素的list
数组
/**
* 生成包含重复元素的list数组
* @return
*/
private static List<String> getList(){
List<String> list = new ArrayList<>();
for (int i = 1; i <= 10000; i++) {
list.add(String.valueOf(i));
}
for (int i = 10000; i >= 1; i--) {
list.add(String.valueOf(i));
}
return list;
}
二、常规方法–使用list.contains()
方法去重
代码实现:
/**
* 使用 list.contains() 方法去重
* @param testList
*/
private static void useListContains(List<String> testList){
System.out.println("contains 开始去重,条数:" + testList.size());
List<String> list = new ArrayList<>();
for (String str : testList) {
if (!list.contains(str)) {
list.add(str);
}
}
System.out.println("contains 去重完毕,条数:" + list.size());
}
测试该方法去重时长:
public static void main(String[] args) {
StopWatch stopWatch = new StopWatch();
// 生成list
List<String> list = getList();
stopWatch.start();
// 常规去重,采用list.contain()
useListContains(list);
stopWatch.stop();
System.out.println("去重共耗时: " + stopWatch.getTotalTimeMillis());
}
结果如下:
list.contains()
去重原理:
以上是ArrayList
中contains
源码的查重逻辑,从源码中我们能看出contains
方法采用的是for
循环遍历数组的方式进行元素的逐一对比,时间复杂度为O(n)
.
三、高效方法–使用HashSet
特性去重
代码实现:
/**
* 使用 hashSet的值不能重复的特性去重
* @param testList
*/
private static void useHashSet(List<String> testList){
System.out.println("hashSet 开始去重,条数:" + testList.size());
List<String> list = new ArrayList<>(new HashSet<>(testList));
System.out.println("hashSet 去重完毕,条数:" + list.size());
}
测试该方法去重时长:
public static void main(String[] args) {
StopWatch stopWatch = new StopWatch();
// 生成list
List<String> list = getList();
stopWatch.start();
// hashSet去重
useHashSet(list);
stopWatch.stop();
System.out.println("去重共耗时: " + stopWatch.getTotalTimeMillis());
}
结果如下:
HashSet
特性去重原理:
new HashSet<>(testList)
新建HashSet
对象时采用的的是add
方法,此处涉及到HashSet
的底层原理,当值相同时,则会添加相同存放位置的链表或者红黑树上,匹对的方法也是直接使用equal
方法进行判断,所以使用HashSet
特性进行去重的时间复杂度为O(1)
.
顺带提一句,HashMap
的containsKey
方法查询key
是否重复的过程时间复杂度也是O(1)
如果不清楚HashSet
底层原理的,可直接通过一下链接了解,图示较为简洁清楚。
HashSet底层原理
四、总结
ArrayList
的 contains
去重时间复杂度为O(n)
HashSet
特性去重的时间复杂度为O(1)
综上,可以得出HashSet
特性去重效率远高于ArrayList
的 contains
去重方法,而且随着查重参数越多,两者的时间差越明显。