关于集合去重的学习总结

以List为例:

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("a");
list.add("b");
list.add("c");

1、最容易想到的就是两层for循环

for(int i = 0; i < list.size(); i++) {
	for(int j = 0; j < list.size(); j++) {
		if(list.get(i).equals(list.get(j))) {
			list.remove(j);
		}
	}
}

这样想没错,但是这样写不对,这样会把重复的值都删除,我们要保留一个重复的值,这里保留第一个,所以二层循环要从一层循环之后开始:

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);
		}
	}
}
这样list结果为[a, b, c, d, e]

但是当list:

List<String> list = new ArrayList<>();
list.add("a");// 0
list.add("b");// 1
list.add("c");// 2
list.add("d");// 3
list.add("e");// 4
list.add("a");// 5  a1
list.add("a");// 6  a2
list.add("b");// 7  b1
list.add("c");// 8
结果就是 [a, b, c, d, e, a]

因为当 i=0 j=5时,会把a1删除,这时a2前进一位角标变成a1的5了,而下一次循环时j=6,这时角标6的值是b1,所以a2就被跳过了判断:

list.add("a");// 0
list.add("b");// 1
list.add("c");// 2
list.add("d");// 3
list.add("e");// 4
list.add("a");// 5  a2
list.add("b");// 6  b1
list.add("c");// 7

采用倒叙遍历可以规避这个问题,两层for循环最终代码:

for (int i = 0; i < list.size(); i++) {
    for (int j = list.size() - 1; j > i; j--) {
        if (list.get(i).equals(list.get(j))) {
            list.remove(j);
        }
    }
}

2、利用List的contains方法

List<String> newList = new ArrayList<>();
for(String s : list) {
    if (!newList.contains(s)) {
        newList.add(s);
    }
}

3、利用HashSet元素不重复的特性

Set<String> set = new HashSet<>(list);
// 如果想得到结果为list:
list = new ArrayList<>(new HashSet<>(list));

4、利用Java8的流操作

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

以上是比较通用的方法,假如集合中重复的值最多只有2个的话,可以用indexOf和lastIndexOf,如果重复的值大于2个删不干净。

 Iterator<String> iterator = list.iterator();
 while (iterator.hasNext()) {
     String next = iterator.next();
     int indexOf = list.indexOf(next);
     int lastIndexOf = list.lastIndexOf(next);
     if (indexOf != lastIndexOf) {
         iterator.remove();
     }
 }

注意: 有的同学在写的时候可能觉得增强for写法简单,这里绝对不能用,因为删除一个值,list.size()就变了,增强for循环会报错。

如果还有好的想法,欢迎留言交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值