常犯错误总结(一)
一、Arrays.asList 与 java.util.ArrayList
1.常用代码:
// 将数组转化为集合 int [] intArray = new int[]{1,2,3,4}; ListasList = Arrays.asList(intArray);
此时 Arrays.asList 转化过程中使用到了一个ArrayList 但此ArrayList 非 java.util.ArrayList 而是 Arrays 内部的一个静态类
2.java.util.Arrays.ArrayList(Arrays的私有内部静态类)
源码分析
// Arrays类中的asList方法 public staticList asList(T... a) { return new ArrayList (a); } // 上面的ArrayList 是Arrays 的内部定义的静态类,而非java.util.ArrayList private static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { if (array==null) throw new NullPointerException(); a = array; } } // 此ArrayList 继承 AbstractList // 而AbstractList 实现 List // 所以 asList 方法可以将 ArrayList 返回给 List public abstract class AbstractList extends AbstractCollection implements List { /** * Sole constructor. (For invocation by subclass constructors, typically * implicit.) */ protected AbstractList() { } }
常用方法
// 定义的私有内部静态类支持常用的方法调用,基本等同于java.util.ArrayList private static class ArrayListextends AbstractList implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { if (array==null) throw new NullPointerException(); a = array; } // 注意此处的size是数组的个数,而不是数组中元素的格式 // int [] intArray = new int[]{1,2,3,4}; // List asList = Arrays.asList(intArray); // System.out.println(asList.size()); // 输出结果是1而不是4 public int size() { return a.length; } public Object[] toArray() { return a.clone(); } public T[] toArray(T[] a) { int size = size(); if (a.length < size) return Arrays.copyOf(this.a, size, (Class extends T[]>) a.getClass()); System.arraycopy(this.a, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } public E get(int index) { return a[index]; } public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } public int indexOf(Object o) { if (o==null) { for (int i=0; i
3.与 java.util.ArrayList 的转化
ListarrayList = new ArrayList (Arrays.asList(integerArray));
4.java.util.Arrays.ArrayList.size()方法
// asList 的参数是 T 泛型,int 是基本数据类型, // 但 int [] 数组是泛型 int [] intArray = new int[]{1,2,3,4}; ListasList = Arrays.asList(intArray); System.out.println(asList.size()); // 1 // asList 的参数是 T ... a ,多个泛型 T // 而Integer 是引用数据类型,此处被解析为传入了多个参数 Integer [] integerArray = new Integer[]{1,2,3,4}; List asList2 = Arrays.asList(integerArray); System.out.println(asList2);// 4
二、判断集合中是否包含某个元素
1.常用代码
Setset = new HashSet (Arrays.asList(arr)); return set.contains(targetValue);
可以改为:
// 因为 java.util.Arrays.ArrayList 有 contain 方法,无需再转为Set Arrays.asList(arr).contains(targetValue);
或
for(String s: arr){ if(s.equals(targetValue)) // Objects.equals(s,targetValue) return true; } return false;
三、删除List中的元素
1.三种想法
ListlistString = new ArrayList (Arrays.asList("a","b","c","d")); // 删除元素后不会出现异常,但要注意删除元素后原来元素的索引会有变化,比如删除a后,此时b的位置要变为0;此时再想删除b已经不可能了,因为index 已经变为1了。即:删除一个特定元素可以 for(int index = 0 ; index < listString.size() ; index ++){ if("a".equals(listString.get(index))){ listString.remove(index); } } for(String str : listString){ if("a".equals(str)){ listString.remove(str); } } // 使用此方式进行删除 Iterator iterator = listString.iterator(); while(iterator.hasNext()){ if("a".equals(iterator.next())){ iterator.remove(); } }
博文参考:
JAVA中循环删除list中元素的方法总结
四、hashMap 与 hashtable
Hashtable
hashMap 线程不安全
hashtable 线程安全
五、使用原始类型的集合
集合与集合泛型
即 List 与 List> 的区别
在使用过程中,如果未指定具体的泛型实现,在对集合进行增删改操作时会因为类型的
1.代码样例
public class ListMainTest { public static void add(List list, Object o) { list.add(o); } public static void main(String[] args) { Listlist = new ArrayList (); add(list, 10); String s = list.get(0); } }
会抛出异常:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
2.异常分析
对 list.get(0) 来说,此时的结果为 Object ,而此时的Object 是通过Integer 类型进行复制的,而接受值的类型却定义为 String ,类型对应错误;
3.总结问题
使用Set> 方式在操作时可以起到类型校验的作用,从而避免上述的问题
六、访问权限
编程习惯,通常定义接口或service 时顺手直接public;
按照 编码规范,应该限制用户的访问权限,直接默认即可
七、ArrayList vs. LinkedList
数组;链表
便于查找,而不利于增删改;后者相反;
ArrayList 实现 RandomAccess ,大量数据遍历时使用 for,随机访问;后者,实现 Deque 双向链表,遍历时 使用 Iterator
博文转载:
十个JAVA程序员容易犯的错误