一般开发者转化数组为ArrayList的方式为java
List<String> list = Arrays.asList(arr);
Arrays.asList()会返回一个ArrayList,而这个ArrayList是Arrays类的静态内部类,不是java.util.ArrayList。数组
这个类有get()、set()和contains()方法,但却没有任何能够添加元素的方法。正确的作法能够这样作安全
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
部分开发者会这样实现数据结构
return new HashSet<String>(Arrays.asList(arr)).contains(targetValue);
结果是对的,可是没有必要转化为Set,这反而会花费更多时间,能够简单这样实现函数
return Arrays.asList(arr).contains(targetValue);
或者性能
for(String s: arr){ if(s.equals(targetValue)) return true; } return false;
补充:第一种相比第二种可读性会高一些。ui
分析一下下列代码:this
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (int i = 0; i < list.size(); i++) { list.remove(i); } System.out.println(list);
输出结果为:线程
[b, d]
设计
由于当数组删除一个元素后,它的长会缩小,index至关于向后移动一位,这是个严重的问题。当你想经过index来删除多个元素时候,这种方法是不可取的。
你也许知道用迭代器来删除是没问题的,而且java中有一类for语句原理就是使用迭代器。但实际你想用这类for语句来代替迭代器进行删除也是不行的,以下代码
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (String s : list) { if (s.equals("a")) list.remove(s); }
将会抛出ConcurrentModificationException异常。
以下代码才是正确的
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); Iterator<String> iter = list.iterator(); while (iter.hasNext()) { String s = iter.next(); if (s.equals("a")) { iter.remove(); } }
next()必须在remove()以前被调用。而在for循环中,编译器会在元素被remove以后调用next(),所以就会抛出ConcurrentModificationException异常。
java中有两类,HashTable和HashMap,二者的数据结构是一致的(哈希表),而后二者的区别是:HashTable是同步的。
因此HashTable是线程安全的,HashMap不是线程安全的。
提示:也可使用ConcurrentHashMap来保证线程安全,ConcurrentHashMap使用分段锁(segment)的原理,效率上会高一些。
在java中,开发者一般把原生态类型(raw type)一般和无界通配符类型(unbounded wildcard type)弄混。拿Set来举例子,Set是原生态类型,而Set<?>是无界通配符类型。
以下代码使用了原生态类型
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 at ...
原生态类型会越过泛型的校验,是不安全的。
有的开发者将类某些属性直接定义为public,这很容易经过外部访问,但绝对是不好的设计。根据拇指规则,最佳作法应该是尽可能减小属性的访问级别。
不少开发者都习惯使用ArrayList,可能ArrayList相对来讲比较熟悉的缘故,其实ArrayList和LinkList仍是存在很大的区别。简而言之,LinkList应该在有大量增删操做且无随机访问操做时候使用。
不可变对象有不少优势,好比简单、安全等。但对于多个值则须要多个不一样的对象来表示,对象过多时,会消耗不少的GC资源。
一般的,可变对象可用来避免产生过多的对象。以下代码中使用了不可变对象,那么执行过程当中将会产生不少的String,消耗不少时间和cpu性能。若是换成可变对象(StringBuilder等),将会好不少。
String result=""; for(String s: arr){ result = result + s; }
class Super { String s; public Super(String s) { super(); this.s = s; } } class Sub extends Super { public Sub(String s) { } public Sub() { } }
上述代码会出错,是由于父类默认构造函数没有定义。在java中,若是一个类没有定义构造函数,则编译器会给它构造默认的无参构造函数。若是类中定义了构造函数,那么编译器将不会给它插入默认构造函数。这个正是上述父类的遇到的状况。
在子类中的两个构造函数中,编译器试图插入父类的默认构造函数super();
,然而并未找到,所以编译出错。
字符串能够经过两种方式创建
//1. 直接引用 String x = "abc"; //2. 使用构造函数 String y = new String("abc");
二者却别可经过以下代码阐明
String a = "abcd"; String b = "abcd"; System.out.println(a == b); // True System.out.println(a.equals(b)); // True String c = new String("abcd"); String d = new String("abcd"); System.out.println(c == d); // False System.out.println(c.equals(d)); // True