List移除相应元素的超简洁写法
最近遇到了一个需求(好吧以前也遇到过),就是将一个List中的部分元素去除,如把string中带数字的元素去除,以前是各种遍历各种不爽,今天发现用Java8中的lambda写,只需三行。
好了上代码
List<String> list = new ArrayList<String>(){
{
// 为list添加数据
addAll(Arrays.asList("wangzhen456liupei123".split("")));
add("1521"); // 纯数字数据
add("wanghzen123") // 数字+字符数据
add("wangzhen"); // 纯字符串
}
};
System.out.println("初始数据:" + list);
Pattern pattern = Pattern.compile("\\d");//匹配数字
Predicate<String> filter = s -> pattern.matcher(s).find();
list.removeIf(filter);//移除
System.out.println(list);
输出如下:
初始数据:[w, a, n, g, z, h, e, n, 4, 5, 6, l, i, u, p, e, i, 1, 2, 3, 1521, wangzhen] [w, a, n, g, z, h, e, n, l, i, u, p, e, i, wangzhen]
其实有机智的朋友可能已经发现了,不要说三行了,一行都可以:
list.removeIf(s -> Pattern.compile("\\d").matcher(s).find());
虽说如果你想这样写也没人能拦着你(同时你也要确定三个月之后依然能看懂)。但是从代码的可读性和可维护性角度来讲,倒是不如前面三行的那个写法。
总结:越精简的代码就越应该有注释,不然哪天手一抽就Ctrl+/了 XD
Java List 删除元素
在Java中,使用List时想要删除某个特定个元素怎么办?很好办!因为List接口有remove()这个方法,我们只需要调用remove()方法,就可以删除list中的某个元素。但是list自带的有一些坑,在相邻有相同元素时会掉坑:
使用list.remove()删除:
我们看到有两个“a”元素相邻,但是删除时却只删除了一个,这是为何呢?因为删除时,每删除一个元素,后边的元素都会左移一位,也就是下标会减1,在for循环中,删除第一个“a”时,i(下标)为0,此时list重排,后边的元素全部左移1位,也就是说第二个“a”元素的下标从1变为了0,而此时for循环进行已经第二次循环了,执行了i++,i的值为1,对应为“b”元素,然后向后循环,再也找不到“a”元素了。所以相邻元素有重复的话,只能删除一个。这明显不符合我们的需求。
那解决办法是什么呢?
1.删除后元素后,i-1
删除一个元素后,后边的元素左移1位,此时i-1,保证了下次循环能访问到左移了1位的元素。
2.反向删除
我们先从后边的元素开始循环,一个一个的往前面循环,找出特定元素删除
这样,就算删除了倒数第一个"a"元素,list重排,也只是把后边的元素左移1位,此时倒数第一个“a”元素(下标为1)被删除,接着b替代了a成为了下标为1的元素,但前边的元素不变,i-- = 0 后依然能够找到其相邻的a元素。
3.使用迭代器删除(iterator)(推荐)
Iterator.remove() 方法会在删除当前迭代对象的同时,会保留原来元素的索引。所以用迭代删除元素是最保险的方法,建议大家使用List过程,这其实和上面第一中方法类似,只不过iterator内部帮我们做了类似i-1的操作。推荐使用这种做法,因为我们不保证每次都记得手动把下标减去1。
4.赋值给新的list
其实我们可以转换思维,可以过滤掉不需要的元素后赋值给新的list对象,利用java8的lambda表达式和强大的stream流形式进行内部迭代来过滤掉特定元素,我们只需一行代码就可以实现。虽然这种方式比较简洁,但是定义了新变量,旧的list就只能等待漫长的gc了。
注意:在进行普通for循环删除时,不要把list.size()抽离出去赋值给变量,然后用此变量做为for条件, 因为删除时,list.size()的值是会改变的,要把list.size作为for条件。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。