03 HashMap

jdk 基于 8 版本

在平时的开发中,我们会经常用到 HashMap, 非常有必要了解源码
HashMap 基于拉链法红黑树来实现,关于这两个算法,这里不做解释。

使用方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class HashMapTest {

    @Test
    void test() {
        Map<String, String> map = new HashMap<>();
        map.put("1", "a");
        map.put("2", "b");
        assertThat(map.remove("1")).isEqualTo("a");
        assertThat(map.put("2", "c")).isEqualTo("b");
        assertThat(map.get("2")).isEqualTo("c");
    }
}

put

源码位置: java.util.HashMap#put

时间轮和线程池实现任务执行器

java 的线程池可以充当一个任务执行器的,但是有时候不符合我们的要求,所以需要自定义开发。
满足1:可以根据任务数量来动态调整核心线程数最大线程数
满足2:支持重复执行的任务。

实现一个软引用缓存

java 中有四种引用类型,分为强引用软引用弱引用虚引用,这里介绍如何使用软引用来实现一个缓存

实现代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class SoftReferenceCache<K, V> implements Cache<K, V> {

    private Map<K, SoftValue<V>> map;

    private ReferenceQueue<V> referenceQueue;

    public SoftReferenceCache() {
        this.map = new HashMap<>();
        this.referenceQueue = new ReferenceQueue<>();
    }

    @Override
    public void put(K key, V value) {
        removeSoftValue();
        this.map.put(key, new SoftValue<>(key, value, referenceQueue));
    }

    @Override
    public V get(K key) {
        removeSoftValue();
        SoftValue<V> softValue = this.map.get(key);
        return softValue.getValue();
    }

    // 这里没有使用额外的线程来定时执行方法
    protected void removeSoftValue() {
        while (true) {
            SoftValue<V> softValue = (SoftValue<V>) referenceQueue.poll();
            if (softValue == null) {
                break;
            }
            System.out.println("remove unnecessary softValue: " + softValue);
            map.remove(softValue.getKey());
        }
    }

    private class SoftValue<V> extends SoftReference<V> {
        
        // 从引用队列中获取此对象,就能知道是哪个key和value要回收了。
        private K key;

        public SoftValue(K key, V value, ReferenceQueue<V> referenceQueue) {
            super(value, referenceQueue);
            this.key = key;
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return super.get();
        }

        @Override
        public String toString() {
            return "SoftValue{" +
                "key=" + key +
                '}';
        }
    }
}

测试代码

注意: 我在 build.gradle 文件中添加了 testjvm 参数 jvmArgs = ["-Xmx10m", “-Xms10m”], 来模拟内存不足来触发回收软引用

01 ArrayList

jdk 基于 8 版本

在平时的开发中,我们会经常用到 ArrayList, 非常有必要了解源码

使用方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class ArrayListTest {

    @Test
    void test() {
        List<String> ids = new ArrayList<>();
        assertThat(ids.add("1")).isEqualTo(true);
        assertThat(ids.add("2")).isEqualTo(true);
        assertThat(ids.add("3")).isEqualTo(true);
        assertThat(ids.remove("2")).isEqualTo(true);
        assertThat(ids.set(0, "4")).isEqualTo("1");
        assertThat(ids.get(0)).isEqualTo("4");
    }
}

add

添加元素到 ArrayList 中,如果空间不够,则触发 newCapacity = oldCapacity + (oldCapacity >> 1)

02 LinkedList

jdk 基于 8 版本

在平时的开发中,我们会经常用到 LinkedList, 非常有必要了解源码

使用方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class LinkedListTest {

    @Test
    void test() {
        List<String> ids = new LinkedList<>();
        assertThat(ids.add("1")).isEqualTo(true);
        assertThat(ids.add("2")).isEqualTo(true);
        assertThat(ids.add("3")).isEqualTo(true);
        assertThat(ids.remove("2")).isEqualTo(true);
        assertThat(ids.set(0, "4")).isEqualTo("1");
        assertThat(ids.get(0)).isEqualTo("4");
    }
}

add

添加元素