1. Array 转 ArrayList
一般开发者喜欢用:
List <String> list = Arrays.asList(arr);
Arrays.asList() 会返回一个 ArrayList, 这是 Arrays 里内嵌的一个私有静态类, 而并不是 java.util.ArrayList 类 java.util.Arrays.ArrayList 有 set(), get(), contains() 方法, 但并支持添加元素, 所以大小是固定的, 想要创建一个真正的 ArrayList, 你应该:
ArrayList < String > arrayList = new ArrayList < String > (Arrays.asList(arr));
关于这个方法更多的解释, 请参见我之前的一篇文章
http://www.cnblogs.com/tina-smile/p/5056174.html
2. 检测一个 Array 是否包含一个元素
一般开发者喜欢用:
- Set < String > set = new HashSet < String > (Arrays.asList(arr));
- return set.contains(targetValue);
这段代码能够工作, 但并没有先转将 list 转为 set,list 转为 set 需要额外时间, 可以用下面更简单的:
Arrays.asList(arr).contains(targetValue);
或者
- for(String s: arr){
- if(s.equals(targetValue))
- return true;
- }
- return false;
第一种方法比第二种的可读性更好
3. 在一个循环中移除 list 中的元素
考虑下下面这种方法:
- 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]
但这种方法有一个严重的问题, 当一个元素被移除的时候, list 的大小就缩减了, 索引也发生了改变所以如果想要在一个循环中使用索引移除多个元素, 这是不可行的
或许你又想用迭代器的方式解决这个问题, 但实际上也不可行, 考虑下下面的代码:
- 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();
- }
- }
- 4.Hashtable vs HashMap
在算法中, 哈希表是数据结构的名称但在 Java 中, 数据结构的名字是 HashMap 中其中一个 Hashtable 和 HashMap 的之间的主要区别是, Hashtable 是同步的所以, 很多时候, 你并不需要哈希表, HashMap 就够用了
5. 使用原始类型的集合
在 Java 中, 原始类型和无界通配符类型很容易混在一起以 Set 为例, 设定为原始类型, 同时 set<?> 是无界的通配符类型
使用原始类型 list, 考虑下面的情况:
- 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 ...
使用原始类型集合是很危险的一件事, 因为它跳过了类属性检测并且是不安全的 Set, Set<?>, and Set
6. 访问权限
很多开发者使用 public 修饰类的字段, 这样很容易获取字段值, 但这是一个糟糕的设计经验法则是给用户尽可能低的访问权限
7.ArrayList vs. LinkedList
大部分的开发者并不知道 ArrayList 和 LinkedList 的区别, 所以经常使用 ArrayList, 这个看起来更熟悉但是, 在这两者之间, 有一个很大的性能差异
简单来说, 在有很多插入和删除操作时, 同时有很少或者几乎没有随机访问的操作情况下, 推荐使用 LinkedList 其次, 再使用 ArrayList
8.Mutable vs. Immutable(可变 VS 不可变)
不可变对象有很多优势这样简单, 安全, 等等但它对于每一个不同的变量, 需要一个单独的对象太多的对象可能会导致高成本的垃圾收集所以在选择可变和不可变的时应该有个权衡
一般来说, 使用可变对象, 以避免产生过多的中间对象一个经典的例子就是连接大量的字符串如果使用不可变的 String, 你会产生很多立马要被垃圾收集回收的对象, 这很消耗时间和精力如果使用一个不可变的, 类似 StringBuffer
- String result = "";
- for (String s: arr) {
- result = result + s;
- }
可变对象还有其他的例子: 函数传参的过程中, 可以传入可变对象, 这样可以得到多个结果
9. 父类和子类的构建
编译出错的原因主要是默认的 Super 类的构造函数并没有被定义在 Java 中, 如果一个类没有实现构造函数, 编译器默认会给这个类插入一个无参构造函数如果在父类中已经有了构造函数, 那么编译器将不会再插入默认无参构造函数
子类的构造函数, 要么是带参的要么是无参的, 都会调用父类的无参构造因为编译器想在子类中, 加入 super(), 但是父类的无参构造函数并不存在所以, 编译器会报错
为了解决这个问题, 有两种解决办法, 第一, 在 Super 类中, 加入无参构造:
- public Super() {
- System.out.println("Super");
- }
第二种方式, 移除自定义的父类构造函数
第三种方式, 子类的构造函数中加入 super(value)
10." or Constructor?
创建一个 String 有两种方式:
- //1. use double quotes
- String x = "abc";
- //2. use constructor
- 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
来源: http://www.codeceo.com/article/10-mistakes-java-programmer.html