remove
问题
现在的需求是移除集合中指定索引的元素,代码如下:
@Test
public void test01() {
List<Integer> list = Arrays.asList(5, 6, 7, 8, 9);
Integer index = 0;
System.out.println(list.remove(index));
}
一开始看不出有什么问题,要实现的是移除索引为0的元素,但是打印的值却是false。
原因
List中有两个名字为remove方法,他们的参数不同,返回值也不同,源码如下:
/**
* Removes the element at the specified position in this list (optional
* operation). Shifts any subsequent elements to the left (subtracts one
* from their indices). Returns the element that was removed from the
* list.
*
* @param index the index of the element to be removed
* @return the element previously at the specified position
* @throws UnsupportedOperationException if the <tt>remove</tt> operation
* is not supported by this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index < 0 || index >= size()</tt>)
*/
E remove(int index);
/**
* Removes the first occurrence of the specified element from this list,
* if it is present (optional operation). If this list does not contain
* the element, it is unchanged. More formally, removes the element with
* the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns <tt>true</tt> if this list
* contained the specified element (or equivalently, if this list changed
* as a result of the call).
*
* @param o element to be removed from this list, if present
* @return <tt>true</tt> if this list contained the specified element
* @throws ClassCastException if the type of the specified element
* is incompatible with this list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* list does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws UnsupportedOperationException if the <tt>remove</tt> operation
* is not supported by this list
*/
boolean remove(Object o);
可见当传递的参数为引用类型的时候,调用的是第二个remove方法,在上面的问题中,实际上是去集合中找0对应的Integer对象,显然找不到,返回false。
Arrays.asList
Arrays.asList()
方法的第一个作用是将数组转化为集合:
public static void main(String[] args) {
String[] strs = {
"java",
"python",
"c#",
"golang"
};
List<String> strList = Arrays.asList(strs);
System.out.println(strList);
}
运行结果:
但是应该注意的是 asList() 的参数为泛型的变长参数,不能使用基本类型数组作为参数,只能使用相应的包装类型数组。
public static void main(String[] args) {
int[] intArr = {1, 2, 3, 4, 5};
List<int[]> list1 = Arrays.asList(intArr);
list1.forEach(arr -> System.out.println(Arrays.toString(arr)));
Integer[] intArr2 = {1, 2, 3, 4, 5};
List<Integer> list2 = Arrays.asList(intArr2);
System.out.println(list2);
}
运行结果:
可见,如果使用基本类型数组作为参数的话,asList
会把参数整体当成集合中的一个元素。
当我们想要快速构建一个集合的时候,我们可以这样写:
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(list); // [1, 2, 3, 4, 5]
}
当传入两个数组的时候:
public static void main(String[] args) {
List<String[]> list2 = Arrays.asList(new String[]{"java", "python"}, new String[]{"golang", "javascript"});
System.out.println(list2); // [[Ljava.lang.String;@2b193f2d, [Ljava.lang.String;@355da254]
}
另外就是,在这个集合中添加元素会发生UnsupportedOperationException
异常:
public static void main(String[] args) {
List<String> list = Arrays.asList("1", "2");
list.add("3");
}
因为Arrays.asList
函数返回的集合虽然名字叫做ArrayList
但是,实际上它是一个内部类,并不是真正的ArrayList
,使用这个内部类的时候,需要注意:
- 该类不支持增删
- 修改该类的元素,会影响原数组
public static void main(String[] args) {
Integer[] arr = {1, 2, 3, 4};
List<Integer> list = Arrays.asList(arr);
arr[0] = 100;
list.set(1, 200);
System.out.println(list); // [100, 200, 3, 4]
System.out.println(Arrays.toString(arr)); // [100, 200, 3, 4]
}
解决方法:外层嵌套一个new ArrayList()
public static void main(String[] args) {
Integer[] arr = {1, 2, 3, 4};
List<Integer> list = new ArrayList<>(Arrays.asList(arr));
arr[0] = 100;
list.set(1, 200);
System.out.println(list); // [1, 200, 3, 4]
System.out.println(Arrays.toString(arr)); // [100, 2, 3, 4]
}
foreach
使用foreach遍历的时候不能删除
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
for (String s : list) {
if ("1".equals(s)) {
list.remove("1");
}
}
// Exception in thread "main" java.util.ConcurrentModificationException
}
详细原因可参考:https://juejin.im/post/5e74413cf265da574c569935
解决方法:
1、使用迭代器删除
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
Iterator<String> iter = list.iterator();
while (iter.hasNext()){
if ("1".equals(iter.next())){
iter.remove();
}
}
System.out.println(list); // [2, 3]
}
2、使用Java8中的removeIf
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.removeIf("1"::equals);
System.out.println(list); // [2, 3]
}
subList
subList分割后的集合和原集合地址相同
public static void main(String[] args) {
ArrayList<String> l1 = new ArrayList<>();
l1.add("1");
l1.add("2");
l1.add("3");
List<String> l2 = l1.subList(0, 1);
l1.set(0, "100");
System.out.println(l1); // [100, 2, 3]
System.out.println(l2); // [100]
}
参考文章:https://mp.weixin.qq.com/s/0kBhhsfb2NBVrgauzUCoLg