常犯错误总结(一)

常犯错误总结(一)


一、Arrays.asList 与 java.util.ArrayList

1.常用代码:
// 将数组转化为集合
int [] intArray = new int[]{1,2,3,4};
List<int[]> asList = Arrays.asList(intArray);


此时 Arrays.asList 转化过程中使用到了一个ArrayList 但此ArrayList 非 java.util.ArrayList 而是 Arrays 内部的一个静态类

2.java.util.Arrays.ArrayList(Arrays的私有内部静态类)
源码分析

    // Arrays类中的asList方法
    public static <T> List<T> asList(T... a) {
	return new ArrayList<T>(a);
    }

    // 上面的ArrayList 是Arrays 的内部定义的静态类,而非java.util.ArrayList
    private static class ArrayList<E> extends AbstractList<E>
	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<E> extends AbstractCollection<E> implements List<E> {
    /**
     * Sole constructor.  (For invocation by subclass constructors, typically
     * implicit.)
     */
    protected AbstractList() {
    }
}


常用方法
    // 定义的私有内部静态类支持常用的方法调用,基本等同于java.util.ArrayList
    private static class ArrayList<E> extends AbstractList<E>
	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<int[]> 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> 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<a.length; i++)
                    if (a[i]==null)
                        return i;
            } else {
                for (int i=0; i<a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }
    }



3.与 java.util.ArrayList 的转化

List<Integer> arrayList = new ArrayList<Integer>(Arrays.asList(integerArray));



4.java.util.Arrays.ArrayList.size()方法

                // asList 的参数是 T 泛型,int 是基本数据类型,
                // 但 int [] 数组是泛型
		int [] intArray = new int[]{1,2,3,4};
		List<int[]> asList = Arrays.asList(intArray);
		System.out.println(asList.size()); // 1
		// asList 的参数是 T ... a  ,多个泛型 T 
                // 而Integer 是引用数据类型,此处被解析为传入了多个参数
		Integer [] integerArray = new Integer[]{1,2,3,4};
		List<Integer> asList2 = Arrays.asList(integerArray);
		System.out.println(asList2);// 4



二、判断集合中是否包含某个元素

1.常用代码
Set<String> set = new HashSet<String>(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.三种想法
		List<String> listString = new ArrayList<String>(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<String> 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) {
		List<String> list = new ArrayList<String>();
		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程序员容易犯的错误

猜你喜欢

转载自mingyundezuoan.iteye.com/blog/2397228