简体   繁体   English

使用HashMap.keySet作为脏副本

[英]Using HashMap.keySet as a dirty copy

I have a requirement where I have to use a hashMap where values can change dynamically and keys can get only inserted not deleted or updated. 我有一个必须使用hashMap的要求,其中值可以动态更改,并且键只能插入而不删除或更新。 However Keys will be read many times and values may be updated many times. 但是,将多次读取键,并且可能会多次更新值。

For latency issues, I haven't made entire HashMap as ConcurrentHashMap in which case while writing keys I will have issues. 对于延迟问题,我没有将整个HashMap做成ConcurrentHashMap,在这种情况下,编写密钥时会遇到问题。 I am fine with compromising slight data accuracy with keys. 我可以通过密钥来降低数据的准确性。 So I decided to keep my own dirty copy of keys. 因此,我决定保留自己的脏密钥副本。 A code snippet like below. 如下所示的代码段。

package com.test.collections;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

public class CheckKeySet {

    private static Map<String, ConcurrentHashMap<String, String>> testMap = new HashMap<String, ConcurrentHashMap<String, String>>();

    public static void main(String[] args) {
        CheckKeySet trial = new CheckKeySet();
        try {
            trial.doIt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void doIt() throws InterruptedException {
        Thread accessThread1 = new AccessKeySet("Access1");
        Thread writeThread = new WriteValueSet();
        Thread accessThread2 = new AccessKeySet("Access2");
        Thread accessThread3 = new AccessKeySet("Access3");

        writeThread.start();
        Thread.sleep(1000);
        accessThread1.start();
        Thread.sleep(2000);
        accessThread2.start();
        Thread.sleep(4000);
        accessThread3.start();
    }

    private Set<String> getKeySet() {
        return new TreeSet<String>(testMap.keySet());
    }

    class AccessKeySet extends Thread {

        public AccessKeySet(String string) {
            super(string);
        }

        @Override
        public void run() {
            Set<String> keySet = getKeySet();
            System.out.println("###############Trying to print########## " + getName() + " keySet size " + keySet.size());
            for (String s : keySet) {
                System.out.println(s);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class WriteValueSet extends Thread {

        @Override
        public void run() {
            int i = 1;
            for (i = 1; i < 10000; i++) {
                testMap.put("Check-" + i, new ConcurrentHashMap<String, String>());
                System.out.println("Inserted " + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

My question, I am creating new Set Object in above implementation with the HashMap.keySet() as base value. 我的问题是,我在上述实现中使用HashMap.keySet()作为基值来创建新的Set对象。 HashMap.keySet() will live forever in my code. HashMap.keySet()将永远存在于我的代码中。 Will this impact the GC of dirty set objects that I am creating in getKeySet() ? 这会影响我在getKeySet()中创建的脏集对象的GC吗? I want this new set object to be cced whenever its holding object becomes eligible for gc. 我希望只要它的持有对象有资格使用gc,就可以抄送这个新的set对象。 It should not be stopped from getting gced because hashMap.keySet is alive 由于hashMap.keySet仍然存在,因此不应停止获取gced

Correct me if I'm wrong, but it sounds like you don't want keys or values to get garbage collected from testMap , unless you manually remove them. 如果我错了,请纠正我,但听起来您不希望从testMap收集垃圾或键或值,除非您手动将其删除。 Rather, you only want keys in the key set returned by your getKeySet() method to be garbage collected, if at all possible, even you might not remove them explicitly from the set. 相反,您只希望对getKeySet()方法返回的键集中的键进行垃圾回收,即使可能的话,即使您可能不明确地从键集中删除它们也是如此。

Assuming that is the case, you should consider using weak references . 假设是这种情况,您应该考虑使用弱引用 More precisely to your implementation, you could simulate a WeakHashSet (as per this answer ) and change your getKeySet() method implementation to: 对于实现而言,您可以模拟一个WeakHashSet (按照此答案 ),并将您的getKeySet()方法实现更改为:

private Set<String> getKeySet() {
  Set<String> cache = Collections.newSetFromMap(
    new WeakHashMap<String, Boolean>());
  cache.addAll(this.testMap.keySet());
  return cache;
}

This new code copies all of the keys of the strongly referenced testMap into the weakly referenced cache . 此新代码将强引用的testMap所有键testMap到弱引用的cache Thus, whenever the garbage collector runs after you remove an element from testMap , the garbage collector will remove that same element automatically from cache . 因此,每当从testMap删除元素后运行垃圾收集器时,垃圾收集器都会从cache自动删除该元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将HashMap.keySet()转换为CharSequence []? - Convert HashMap.keySet() to CharSequence[]? Hashmap.keySet(),foreach和remove - Hashmap.keySet(), foreach, and remove hashmap.keyset()会按照它们添加到hashmap的顺序返回键吗? - Will hashmap.keyset() return keys in the order they were added to the hashmap? HashMap.keySet()如何返回键的视图? - How can HashMap.keySet() return a view of keys? HashMap.KeySet()在Java 7中以不同顺序返回键Java 8 - HashMap.KeySet() returns keys in different order in Java 7 Java 8 HashMap.values()/ HashMap.keySet()何时按引用返回,何时按值返回? - When Does HashMap.values()/HashMap.keySet() Return By Reference And When Does It Return By Value? HashMap.values()和HashMap.keySet()如何返回值和键? - How do HashMap.values() and HashMap.keySet() return values and keys? 在HashMap中使用keySet()方法 - Using the keySet() method in HashMap 如何从Java Rest服务在引导表中显示Java Hashmap.keySet()? - How to display Java Hashmap.keySet() in a bootstrap table, from a java rest service? 是什么导致java.util.HashSet和HashMap.keySet()类的iterator()稍微不可预测的排序? - What causes the slightly unpredictable ordering of the iterator() for the java.util.HashSet and HashMap.keySet() classes?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM