zl程序教程

您现在的位置是:首页 >  后端

当前栏目

java list去重_JAVA基础-List去重的6种方式[通俗易懂]

JAVAList基础 通俗易懂 方式
2023-06-13 09:11:46 时间

大家好,又见面了,我是你们的朋友全栈君。

简述

java开发中经常会遇到List去重这个工作,现在就来整理一下List去重的6种方式。

方法代码以及效率测试

模拟测试数据

相关代码:

import java.util.LinkedList;

import java.util.List;

/**

* @ClassName: ListCleatMain

* @Description: 模拟数据进行List去重测试

* @author: ssqxx

* @date: 2020-11-18

* @version 1.0

*/

public class ListCleatMain {

public static void main(String[] args) {

//声明一个新的List

List list = new LinkedList<>();

//数据装载开始时间

Long startTime = System.currentTimeMillis();

System.out.println(“数据装载开始时间:” + startTime);

//模拟添加200000个Integer

for (int i=0;i<200000;i++){

Integer in =(int)(Math.random()*10+1);

list.add(in);

}

//数据装载结束时间

Long endTime = System.currentTimeMillis();

System.out.println(“数据装载结束时间:” + endTime);

//数据装载时差

System.out.println(“数据装载时差:” + (endTime – startTime));

//原数据遍历打印

System.out.println(“原数据:”);

list.forEach( li-> {

System.out.print(li + ” “);

});

System.out.println();

//开始时间

long startClear = System.currentTimeMillis();

System.out.println(“开始时间:” + startClear);

//去重-双for循环去重

List newList = ListClearByDoubleFor.listRemove(list);

//去重-Contains方法去重

// List newList = ListClearByContains.listRemove(list);

//去重-利用HashSet去重

// List newList = ListClearByHashSet.listRemove(list);

//去重-利用TreeSet去重

// List newList = ListClearByTreeSet.listRemove(list);

//去重-利用LinkedHashSet去重

// List newList = ListClearByLinkedHashSet.listRemove(list);

//去重-利用Java8的stream去重

// List newList = ListClearByStream.listRemove(list);

//结束时间

long endClear = System.currentTimeMillis();

System.out.println(“结束时间:” + endClear);

//时间差

System.out.println(“去重用时:” + (endClear – startClear));

//去重后数据遍历打印

System.out.println(“新数据:”);

newList.forEach(li -> {

System.out.print(li + ” “);

});

}

}

双for循环

实现思想:

使用两个for循环遍历集合所有元素,然后进行判断是否有相同元素,如果有,则去除。(有序)

相关代码:

import java.util.List;

/**

* @ClassName: ListClearByDoubleFor

* @Description: 双for循环进行list去重

* @author: ssqxx

* @date: 2020-11-18

* @version 1.0

*/

public class ListClearByDoubleFor {

/**

* 数据去重

* @param list

* @return list

*/

public static List listRemove(List list){

//双for循环进行list去重

for (int i=0; i

for (int j=i+1; j

if (list.get(i).equals(list.get(j))){

list.remove(j);

j–;

}

}

}

return list;

}

}

效率测试:

数据装载开始时间:1605667320390

数据装载结束时间:1605667320407

数据装载时差:17

原数据:

9 8 3 2 3 10 4 9 5 3 1 7 6 8 7 8 9 5 5 8 2 2 ……(20W数据)

开始时间:1605667320811

结束时间:1605667413269

去重用时:92458(这还用再测?)

新数据:

9 8 3 2 10 4 5 1 7 6

————————————————–

它不配!!!!!

List的contains方法

实现思想:

利用List集合contains方法循环遍历,先创建新的List集合,接着循环遍历原来的List集合,判断新集合是否包含有旧集合,如果有,则不添加至新集合,否则添加。(有序)

相关代码:

import java.util.ArrayList;

import java.util.List;

/**

* @ClassName: ListClearByContains

* @Description: 利用List集合contains方法循环遍历去重

* @author: ssqxx

* @date: 2020-11-18

* @version 1.0

*/

public class ListClearByContains {

/**

* 数据去重

* @param list

* @return list

*/

public static List listRemove(List list){

//利用List集合contains方法循环遍历去重

List newList = new ArrayList();

list.forEach(li -> {

//判断新集合是否包含有,如果不包含有,则存入新集合中

if (!newList.contains(li)){

newList.add(li);

}

});

return newList;

}

}

效率测试:

数据装载开始时间:1605674583323

数据装载结束时间:1605674583340

数据装载时差:17

原数据:

8 10 7 3 7 6 6 1 7 6 2 8 9 6 6 5 2 6 5 5 3 1 ……(20W数据)

开始时间:1605674583756

结束时间:1605674583771

去重用时:15/13/13/13/11(5次测试)

新数据:

8 10 7 3 6 1 2 9 5 4

————————————————–

开始时间:1605680194498

结束时间:1605680194553

去重用时:55/57/56/61/64(打印原数据)

去重用时:144/120/127/124/125(不打印原数据)

新数据:

17 3 2 16 13 6 18 1 10 5 11 7 20 9 15 14 12 8 19 4

HashSet方法

实现思想:

HashSet实现了Set接口,不允许出现重复元素。可以基于这个想法,把List集合所有元素存入HashSet对象,接着把List集合元素全部清空,最后把HashSet对象元素全部添加至List集合中,这样就可以保证不出现重复元素。而HashSet有一个构造函数,在初始化时可以直接添加元素。其中,HashSet不能保证顺序不变,所以此方式不能保证List集合原来的顺序不变。 (无序)

相关代码:

import java.util.HashSet;

import java.util.Iterator;

import java.util.List;

/**

* @ClassName: ListClearByHashSet

* @Description: List集合放入HashSet中利用HashSet实现Set接口的无重复元素特性去重

* @author: ssqxx

* @date: 2020-11-18

* @version 1.0

*/

public class ListClearByHashSet {

/**

* 数据去重

* @param list

* @return list

*/

public static List listRemove(List list){

//List集合放入HashSet中利用HashSet实现Set接口的无重复元素特性去重

HashSet set = new HashSet(list);

list.clear();

list.add(set);

// Iterator it = set.iterator();

// while (it.hasNext()){

// list.add(it.next());

// }

return list;

}

}

效率测试:

数据装载开始时间:1605675392758

数据装载结束时间:1605675392776

数据装载时差:18

原数据:

3 6 1 1 7 6 9 2 8 6 4 7 1 9 5 5 4 3 3 1 10 8 10 10……(20w数据)

开始时间:1605675393184

结束时间:1605675393200

去重用时:16/20/15/12/15(5次测试)

新数据:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

————————————————–

开始时间:1605680088596

结束时间:1605680088641

去重用时:45/45/46/52/44(打印原数据)

去重用时:167/163/160/164/166(不打印原数据)

新数据:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

TreeSet方法

实现思想:

TreeSet集合也是实现Set接口,是一个有序的,并且无重复元素集合。(有序)

相关代码:

import java.util.*;

/**

* @ClassName: ListClearByTreeSet

* @Description: List集合放入TreeSet中利用HashSet实现Set接口的无重复元素特性去重

* @author: ssqxx

* @date: 2020-11-18

* @version 1.0

*/

public class ListClearByTreeSet {

/**

* 数据去重

* @param list

* @return list

*/

public static List listRemove(List list){

//List集合放入TreeSet中利用HashSet实现Set接口的无重复元素特性去重

TreeSet set = new TreeSet(list);

list.clear();

list.add(set);

// Iterator it = set.iterator();

// while (it.hasNext()){

// list.add(it.next());

// }

return list;

}

}

效率测试:

数据装载开始时间:1605675683470

数据装载结束时间:1605675683487

数据装载时差:17

原数据:

8 10 4 3 8 10 8 2 1 9 1 3 1 1 8 3 4 4 10 6 6 2……(20W数据)

开始时间:1605675683881

结束时间:1605675683909

去重用时:28/25/29/26/26(5次测试)

新数据:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

————————————————–

开始时间:1605679953606

结束时间:1605679953697

去重用时:91/94/104/103/101(打印原数据)

去重用时:112/119/123/113/117(不打印原数据)

新数据:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

LinkedHashSet方法

实现思想:

LinkedHashSet是一个实现Set接口将ArrayList删除重复数据的最佳方法。LinkedHashSet在内部完成两件事:删除重复数据,保持添加到其中的数据的顺序。(有序)

相关代码:

import java.util.*;

/**

* @ClassName: ListClearByLinkedHashSet

* @Description: List集合放入LinkedHashSet中利用LinkedHashSet实现Set接口的无重复元素特性去重

* @author: ssqxx

* @date: 2020-11-18

* @version 1.0

*/

public class ListClearByLinkedHashSet {

/**

* 数据去重

* @param list

* @return list

*/

public static List listRemove(List list){

//List集合放入LinkedHashSet中利用LinkedHashSet实现Set接口的无重复元素特性去重

LinkedHashSet hashSet = new LinkedHashSet(list);

list.clear();

list.add(hashSet);

// Iterator iterator = hashSet.iterator();

// while(iterator.hasNext()){

// list.add(iterator.next());

// }

return list;

}

}

效率测试:

数据装载开始时间:1605675839400

数据装载结束时间:1605675839417

数据装载时差:17

原数据:

2 7 5 1 4 4 1 5 1 9 10 7 3 9 7 3 6 7 1 1 4……(20W数据)

开始时间:1605675839818

结束时间:1605675839835

去重用时:17/16/14/17/19(5次测试)

新数据:

[2, 7, 5, 1, 4, 9, 10, 3, 6, 8]

————————————————–

开始时间:1605679823889

结束时间:1605679823938

去重用时:49/43/42/42/44(打印原数据)

去重用时:173/159/160/163/169(不打印原数据)

新数据:

[12, 1, 9, 6, 3, 8, 19, 13, 5, 16, 2, 10, 11, 15, 17, 4, 7, 20, 14, 18]

Java8的stream方法

实现思想:

要从arraylist中删除重复项,我们也可以使用java 8 stream api。使用steam的distinct()方法返回一个由不同数据组成的流,通过对象的equals()方法进行比较。 (有序)

相关代码:

import java.util.List;

import java.util.stream.Collectors;

/**

* @ClassName: ListClearByStream

* @Description: 使用java8新特性stream实现List去重

* @author: ssqxx

* @date: 2020-11-18

* @version 1.0

*/

public class ListClearByStream {

/**

* 数据去重

* @param list

* @return list

*/

public static List listRemove(List list){

//使用java8新特性stream实现List去重

List newList = (List) list.stream().distinct().collect(Collectors.toList());

return newList;

}

}

效率测试:

数据装载开始时间:1605679132825

数据装载结束时间:1605679132841

数据装载时差:16

原数据:

7 3 4 6 5 2 7 8 5 6 7 4 3 8 6 5 2 4 5 5 2 10 2……(20W数据)

开始时间:1605679133233

结束时间:1605679133248

去重用时:15/14/13/19/16(5次测试)

新数据:

7 3 4 6 5 2 8 10 9 1

————————————————–

开始时间:1605679582415

结束时间:1605679582443

去重用时:28/31/35/27/31(打印原数据)

去重用时:94/81/96/96/87(不打印原数据)

新数据:

8 15 4 3 17 1 10 19 12 9 16 20 7 6 18 13 2 5 14 11

结论

随机数在200000范围10以内(平均值):

使用两个for循环实现List去重:94258毫秒

使用List集合contains方法循环遍历去重时间:13毫秒

使用HashSet实现List去重时间:16毫秒

使用TreeSet实现List去重时间:27毫秒

使用LinkedHashSet实现List去重时间:17毫秒

使用java8新特性stream实现List去重:15毫秒

随机数在2000000范围20以内(平均值):

使用两个for循环实现List去重:已放弃!!!!

使用List集合contains方法循环遍历去重时间:128毫秒

使用HashSet实现List去重时间:164毫秒

使用TreeSet实现List去重时间:117毫秒

使用LinkedHashSet实现List去重时间:165毫秒

使用java8新特性stream实现List去重:91毫秒

随机数在20000000范围20以内(一次值):

使用两个for循环实现List去重:已放弃!!!!

使用List集合contains方法循环遍历去重时间:612毫秒

使用HashSet实现List去重时间:334毫秒

使用TreeSet实现List去重时间:813毫秒

使用LinkedHashSet实现List去重时间:364毫秒

使用java8新特性stream实现List去重:214毫秒

结论简述:

目前表现最好的是java8新特性stream实现的list去除,不论是数据量大小;

HashSet、TreeSet、LinkedHashSet都有实现Set接口,所以速度都不会很慢,但是在过了1000W这个数量的list后去重速度骤降,HashSet,LinkedHashSet依旧稳定快速;整体上HashSet>LinkedHashSet>TreeSet。不过HashSet是无序的,若想有序可以使用LinkedHashSet;

list集合的contains方法在数据量不大的时候能去重速度也挺快的,甚至能超过HashSet,但数据量大(500W)之后,去重速度骤降,数据量不大的list去重可以使用;

双for循环进行list去重就……算了,放弃吧!

整体排序:

500W数据以下:

(有序)stream>contains>LinkedHashSet>TreeSet>for

(无序)stream>contains>HashSet>LinkedHashSet>TreeSet>for

500W数据以上:

(有序)stream>LinkedHashSet>contains>TreeSet>for

(无序)stream>HashSet>LinkedHashSet>contains>TreeSet>for

以上数据为自测数据,可能与实际应用会存在误差,下次再测试一下String(字符串)的list排序。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/141516.html原文链接:https://javaforall.cn