Rumah  >  Artikel  >  Java  >  Bagaimana untuk menulis kod pelaksanaan koleksi java

Bagaimana untuk menulis kod pelaksanaan koleksi java

WBOY
WBOYke hadapan
2023-05-05 23:04:051049semak imbas

1. HashMap

public class HashMapDemo {
    private Map map = null;
    public void init() {
        map = new HashMap();
        map.put("a", "aaa");
        map.put("b", "bbb");
        map.put("c", "ccc");
        System.out.println(map);
    }
    // 添加元素
    public void testPut() {
        // V put(K key, V value) :把指定的key和value添加到集合中
        map.put("a1", "aaa");
        map.put("b1", "bbb");
        map.put("c1", "ccc");
        System.out.println(map);
        // void putAll(Map<? extends K,? extends V>m) :把指定集合添加集合中
        Map map1 = new HashMap();
        map1.put("e", "eee");
        map1.put("f", "fff");
        map.putAll(map1);
        System.out.println(map);
        // default V putIfAbsent(K key, V value) :如果key不存在就添加
        map.putIfAbsent("a", "hello");
        System.out.println(map);
        map.putIfAbsent("g", "ggg");
        System.out.println(map);
    }
    // 修改元素
    public void testModify() {
        // V put(K key, V value) :把集合中指定key的值修改为指定的值
        map.put("a", "hello");
        map.put("a", "world");
        System.out.println(map);
        // 说明,当key相同时,后面的值会覆盖前面的值。
        // default V replace(K key, V value) :根据key来替换值,而不做增加操作
        Object replace = map.replace("b1", "java");
        System.out.println(replace);
        System.out.println(map);
        //default boolean replace(K key, V oldValue,V newValue)
    }
    // 删除元素
    public void testRemove() {
        // V remove(Object key) :根据指定key删除集合中对应的值
        Object c = map.remove("c");
        System.out.println(c);
        System.out.println(map);
        // default boolean remove(Object key, Objectvalue) :根据key和value进行删除
        map.remove("b", "bbb1");
        System.out.println(map);
        // void clear() :清空集合中所有元素
        map.clear();
        System.out.println(map);
    }
    // 判断元素
    public void testJudge() {
        // boolean isEmpty() :判断集合是否为空,如果是返回true,否则返回false
        System.out.println(map.isEmpty());
        // boolean containsKey(Object key) :判断集合中是否包含指定的key,包含返回true,否则返回false
        boolean flag = map.containsKey("a");
        System.out.println(flag); // true
        flag = map.containsKey("a1");
        System.out.println(flag); // false
        // boolean containsValue(Object value) :判断集合中是否包含指定的value,包含返回true,否则返回false
        flag = map.containsValue("aaa");
        System.out.println(flag); // true
        flag = map.containsValue("aaa1");
        System.out.println(flag); // false
    }
    // 获取元素
    public void testGet() {
        // int size() :返回集合的元素个数
        int size = map.size();
        System.out.println(size);
        // V get(Object key) :根据Key获取值,如果找到就返回对应的值,否则返回null
        Object val = map.get("a");
        System.out.println(val);
        val = map.get("a1");
        System.out.println(val); // null
        // default V getOrDefault(Object key, VdefaultValue) :根据Key获取值,如果key不存在,则返回默认值
        val = map.getOrDefault("a1", "hello");
        System.out.println(val);
        // Collection<V> values() :返回集合中所有的Value
        Collection values = map.values();
        for (Object value : values) {
            System.out.println(value);
        }
        // Set<K> keySet() :返回集合中所有的Key
        Set set = map.keySet();
        for (Object o : set) {
            System.out.println(o);
        }
    }
    // 迭代元素
    public void testIterator() {
        // 第一种:通过key获取值的方式
        Set keySet = map.keySet();
        Iterator it = keySet.iterator();
        while (it.hasNext()) {
            Object key = it.next();
            Object val = map.get(key);
            System.out.println(key + "=" + val);
        }
        System.out.println("------------------------ ");
        // 第二种:使用for循环
        for (Object key : map.keySet()) {
            System.out.println(key + "=" +
                               map.get(key));
        }
        System.out.println("------------------------ ");
        // 第三种:使用Map接口中的内部类来完成,在框架中大量使用
        Set entrySet = map.entrySet();
        for (Object obj : entrySet) {
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "=" +
                               entry.getValue());
        }
    }
}

Nota: Dalam HashMap, nilai kunci dibenarkan kosong, tetapi kuncinya unik dan nilainya boleh diulang. hashMap tidak selamat untuk benang.

2. TreeMap

ialah koleksi tersusun, menggunakan pengisihan semula jadi secara lalai.

public class Person implements Comparable {
    private String name;
    private int age;
    @Override
    public int compareTo(Object o) {
    if (o instanceof Person) {
    Person p = (Person) o;
    return this.age - p.age;
    }
    return 0;
}
    public Person() {}
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

Ujian

public class TeeMapDemo {
    @Test
    public void testInteger() {
        TreeMap tm = new TreeMap();
        tm.put(3, 333);
        tm.put(2, 222);
        tm.put(11, 111);
        tm.put(2, 222);
        System.out.println(tm);
    }
    @Test
    public void testString() {
        TreeMap tm = new TreeMap();
        tm.put("hello", "hello");
        tm.put("world", "world");
        tm.put("about", "");
        tm.put("abstract", "");
        System.out.println(tm);
    }
    @Test
    public void testPerson() {
        TreeMap tm = new TreeMap(new Comparator(){
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Person && o2
                    instanceof Person) {
                    Person p1 = (Person) o1;
                    Person p2 = (Person) o2;
                    return p1.getAge() - p2.getAge();
                }
                return 0;
            }
        });
        tm.put(new Person("张三",18), null);
        tm.put(new Person("李四",17), null);
        System.out.println(tm);
    }
}

Penjelasan: Daripada kod di atas, kita dapati bahawa penggunaan TreeMap sangat serupa dengan penggunaan TreeSet Memerhati kod sumber koleksi HashSet, kita boleh lihat bahawa apabila mencipta koleksi HashSet, Malah, lapisan bawah menggunakan HashMap.

public HashSet() {
	map = new HashMap<>();
}

HashSet sebenarnya menyimpan Kunci HashMap.

3.ConcurrentHashMap

Dalam koleksi Map yang kami perkenalkan HashMap, TreeMap Dalam kes multi-threading, koleksi ini tidak selamat untuk thread, jadi thread-safety mungkin berlaku.

Di Java, Hashtable adalah selamat untuk thread HashMap tidak berbeza dengan Hashtable dari segi kaedah Ia hanya menggunakan HashMap untuk mencapai keselamatan thread tujuan, kami memerhatikan kod sumber Hashtable. synchronized

public synchronized V get(Object key) {
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return (V)e.value;
            }
        }
        return null;
    }
Di atas adalah mendapatkan kod sumber Hashtable Ia dapat dilihat bahawa ia hanya menambah kunci kepada kaedah, yang sangat mengurangkan kecekapan pelaksanaan utas dan mencapai matlamat dengan mengorbankan kecekapan. Ini jelas bukan perkara yang kami mahukan dalam amalan, jadi kami memerlukan kaedah yang selamat dan cekap.

ConcurrentHashMap menggunakan prinsip kunci bersegmen. Mari kita perhatikan kod sumber.

 public V put(K key, V value) {
        return putVal(key, value, false);
    }
final V putVal(K key, V value, boolean onlyIfAbsent) {
        if (key == null || value == null) throw new NullPointerException();
        int hash = spread(key.hashCode());
        int binCount = 0;
        for (Node<K,V>[] tab = table;;) {
            Node<K,V> f; int n, i, fh;
            if (tab == null || (n = tab.length) == 0)
                tab = initTable();
            else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
                if (casTabAt(tab, i, null,
                             new Node<K,V>(hash, key, value, null)))
                    break;                   // no lock when adding to empty bin
            }
            else if ((fh = f.hash) == MOVED)
                tab = helpTransfer(tab, f);
            else {
                V oldVal = null;
                synchronized (f) {
                    if (tabAt(tab, i) == f) {
                        if (fh >= 0) {
                            binCount = 1;
                            for (Node<K,V> e = f;; ++binCount) {
                                K ek;
                                if (e.hash == hash &&
                                    ((ek = e.key) == key ||
                                     (ek != null && key.equals(ek)))) {
                                    oldVal = e.val;
                                    if (!onlyIfAbsent)
                                        e.val = value;
                                    break;
                                }
                                Node<K,V> pred = e;
                                if ((e = e.next) == null) {
                                    pred.next = new Node<K,V>(hash, key,
                                                              value, null);
                                    break;
                                }
                            }
                        }
                        else if (f instanceof TreeBin) {
                            Node<K,V> p;
                            binCount = 2;
                            if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
                                                           value)) != null) {
                                oldVal = p.val;
                                if (!onlyIfAbsent)
                                    p.val = value;
                            }
                        }
                    }
                }
                if (binCount != 0) {
                    if (binCount >= TREEIFY_THRESHOLD)
                        treeifyBin(tab, i);
                    if (oldVal != null)
                        return oldVal;
                    break;
                }
            }
        }
        addCount(1L, binCount);
        return null;
    }
Ia boleh dilihat daripada kod sumber bahawa

hanya menambah kunci apabila benang mengendalikan data semasa, jadi kecekapan dipertingkatkan dengan banyak. ConcurrentHashMap

Meningkatkan kecekapan sambil selamat untuk benang.

Atas ialah kandungan terperinci Bagaimana untuk menulis kod pelaksanaan koleksi java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam