编写高质量代码:改善Java程序的151个建议 --[65~78]

编写高质量代码:改善Java程序的151个建议 --[65~78]

原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱。
public class Client65 {
    public static void main(String[] args) {
        int data [] = {1,2,3,4,5};
        List list= Arrays.asList(data);
        System.out.println("元素类型是:"+list.get(0).getClass());
        System.out.println("前后是否相等:"+data.equals(list.get(0)));    
    }
}

输出的结果是: 元素类型是:class [I 前后是否相等:true
如果要转换,建议转换为对应的包装类,再使用 List list= Arrays.asList(data)来转换

asList方法产生的List的对象不可更改

添加修改Arrays.asList后的list数据会产生如下错误

在修改动作上,LinkedList比ArrayList慢很多,特别是要进行大量的修改时,两者完全不在一个数量级上。
LinkedList删除和插入效率高;ArrayList修改元素效率高。

判断集合是否相等时只须关注元素是否相等即可
import java.util.ArrayList;
import java.util.Vector;

public class Client69 {
    public static void main(String[] args) {
        ArrayList<String> strs = new ArrayList<String>();
        strs.add("A");

        Vector<String> strs2 = new Vector<String>();
        strs2.add("A");

        System.out.println(strs.equals(strs2));
    }
}

AbstractList看下源码:

public boolean equals(Object o) {
            if (o == this)
                return true;
            //是否是列表,注意这里:只要实现List接口即可
            if (!(o instanceof List))
                return false;
            //通过迭代器访问List的所有元素
            ListIterator<E> e1 = listIterator();
            ListIterator e2 = ((List) o).listIterator();
            //遍历两个List的元素
            while (e1.hasNext() && e2.hasNext()) {
                E o1 = e1.next();
                Object o2 = e2.next();
                //只要存在着不相等就退出
                if (!(o1==null ? o2==null : o1.equals(o2)))
                    return false;
            }
            //长度是否也相等
            return !(e1.hasNext() || e2.hasNext());
        }
子列表只是原列表的一个视图

SubList类也是AbstractList的子类,其所有的get、set、add、remove等都是在原始列表上的操作,它自身并没有生成一个新的数组或是链表,也就是子列表只是原列表的一个视图(View)而已。所有的修改动作都映射到了原列表上。

实现了compareTo方法就应该覆写equals方法,确保两者同步

indexOf依赖equals方法查找,binarySearch则依赖compareTo方法查找;
equals是判断元素是否相等,compareTo是判断元素在排序中的位置是否相同。
既然一个决定排序位置,一个是决定相等,那我们就应该保证当排序相同时,其equals也相同,否则就会产生逻辑混乱。

集合运算时使用最优雅方式

并集:

public static void main(String[] args) {
        List<String> list1 = new ArrayList<String>();
        list1.add("A");
        list1.add("B");
        List<String> list2 = new ArrayList<String>();
        list2.add("C");
        // 并集
        list1.addAll(list2);
    }

交集:

//交集
list1.retainAll(list2);

差集:

//差集
list1.removeAll(list2);

无重复的并集:

 	   //删除在list1中出现的元素
        list2.removeAll(list1);
        //把剩余的list2元素加到list1中
        list1.addAll(list2);
使用shuffle打乱列表

举个栗子:

public static void main(String[] args) {
        int tagCloudNum = 10;
        List<String> tagClouds = new ArrayList<String>(tagCloudNum);
        // 初始化标签云,一般是从数据库读入,省略
        //打乱顺序
        Collections.shuffle(tagClouds);
    }

shuffle使用场景:

  1. 可用在程序的 "伪装" 上:比如我们例子中的标签云,或者是游侠中的打怪、修行、群殴时宝物的分配策略。
  2. 可用在抽奖程序中:比如年会的抽奖程序,先使用shuffle把员工顺序打乱,每个员工的中奖几率相等,然后就可以抽出第一名、第二名。
  3. 可以用在安全传输方面:比如发送端发送一组数据,先随机打乱顺序,然后加密发送,接收端解密,然后进行排序,即可实现即使是相同的数据源,也会产生不同密文的效果,加强了数据的安全性。
posted @ 2018-08-09 17:41  西北野狼  阅读(392)  评论(0编辑  收藏  举报