zoukankan      html  css  js  c++  java
  • java-集合类(二)

    使用场景

    1.多线程

    (1)在jdk1.5之前原始的集合类中,仅仅有vector、stack、hashtable、enumeration等是线程安全的,其它的都是非线程安全的。


    非线程安全的集合在多线程操作中,会出现脏数据,如

    final List<String> tickets = new ArrayList<String>();
            for (int i = 0; i < 100000; i++) {
                tickets.add("NO," + i);
            }
            System.out.println("start1...");
            for (int i = 0; i < 5; i++) {
                Thread thread = new Thread() {
                    public void run() {
                        while (true) {
                            if (tickets.size() > 0)
     System.out.println("thread:"+Thread.currentThread().getId()+" "+ tickets.remove(0));
                            else
                                break;
                        }
                    }
                };
                thread.start();
            }

    执行结果:

    ......
    thread:13 NO,98687
    thread:12 NO,96534
    thread:10 NO,96534
    thread:10 NO,98687
    ......
    thread:10 null
    thread:12 null

    线程不安全导致多个线程调用 remove 时同一时候操作 List 进行读写。
    ArrayList改动成 Stack,问题解决。
    (2)线程安全的集合也须要遵守fail-fast的检測机制,即在迭代的时候,不能改动集合的元素。一旦发现违反这个规定就会抛出ConcurrentModificationException异常。

    如需在迭代过程中改动元素,须要对迭代和改动加同步锁。


    如以下代码将出现ConcurrentModificationException异常。

    final List<String> tickets = Collections
                    .synchronizedList(new ArrayList<String>());
            for (int i = 0; i < 100; i++) {
                tickets.add("NO," + i);
            }
            System.out.println("start1...");
            for (int i = 0; i < 5; i++) {
                Thread thread = new Thread() {
                    public void run() {
                        while (true) {
                            if (tickets.size() > 0)
                                System.out.println("thread:"
                                        + Thread.currentThread().getId() + " "
                                        + tickets.remove(0));
                            else
                                break;
                        }
                    }
                };
                thread.start();
            }
    
            System.out.println("start2...");
            new Thread() {
                public void run() {
                    for (String s : tickets) {
                        System.out.println(s);
                    }
                }
            }.start();

    (3)获取线程安全的集合
    1.使用vector、stack、hashtable、enumeration等线程安全的集合类。
    2.使用Collections.synchronizedxxx 将非线程安全的集合转换成线程安全的集合。
    3.使用 jdk1.5之后新的线程安全集合类。如ConcurrentLinkedQueue、ConcurrentHashMap等。

    2.使用注意事项

    (1)ArrayList 等顺序存放集合适合随机訪问,LinkList 等链表形式存放集合适合插入删除和迭代操作。


    (2)Collection接口继承了Iterable接口,除 map 外每一个集合都支持迭代遍历和 foreach 功能。
    (3)WeakHashMap支持 key 回收。提升性能,在开源项目Android-Universal-Image-Loader 中用WeakHashMap保存须要显示的 ImageView 支持回收。
    (4)HashMap 的 key 推断同样的标准是 key 的 equal 和 hashcode 同样。例如以下

    private static void testHashMapKey() {
            System.out.println("------test hash map key start------");
            String[] sampleTest = { "Aa", "BB", "aa" };
            HashMap<StringEqual, Integer> strHaspMap = new HashMap<HashMapDemo.StringEqual, Integer>();
            StringEqual[] strArray = { new StringEqual(sampleTest[0]),
                    new StringEqual(sampleTest[1]), new StringEqual(sampleTest[2]) };
            //key是否同样的推断是equal和hash都同样,Aa和BB的hash同样
            strHaspMap.put(strArray[0], 0);
            strHaspMap.put(strArray[1], 1);
            strHaspMap.put(strArray[2], 2);
            Set<StringEqual> set = strHaspMap.keySet();
            for (StringEqual str : set) {
                System.out.println(strHaspMap.get(str));
            }
        }
    
        private static class StringEqual {
            private String str;
    
            public StringEqual(String str) {
                this.str = str;
            }
    
            @Override
            public boolean equals(Object obj) {
                return true;
            }
    
            @Override
            public int hashCode() {
                return str.hashCode();
            }
        }
    ------test hash map key start------
    1
    2

    String 的 hashcode 算法是s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1]。”Aa”和”BB”的hash同样,StringEqual类的 equal 默觉得 true,则”Aa”和”BB”认定为同一个 key。

  • 相关阅读:
    网页表格或div层在网页中被撑开解决之道
    jquery把给定的json自动生成多级下拉框
    jquery理想菜单实现(显示全国省市区分级效果)
    正则表达式记录
    jQuery自定义插件
    js数组及其常用方法
    vue自定义组件
    GET和POST
    可变对象和不可变对象
    js 不同元素的同一属性运动
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7100377.html
Copyright © 2011-2022 走看看