Java集合和内存优化(Java collection and memory optimizatio

2019-09-21 06:14发布

我写了一个自定义索引到使用堆的500MB为500K字符串自定义表。 只有10%的字符串是独一无二的; 其余的都是重复的。 每串是长度为4的。

如何我可以优化我的代码? 我应该使用另一个集合? 我试图实现一个自定义字符串池以节省内存:

public class StringPool {

    private static WeakHashMap<String, String> map = new WeakHashMap<>();

    public static String getString(String str) { 
        if (map.containsKey(str)) {
            return map.get(str);
        } else {
            map.put(str, str);
            return map.get(str);
        }
    }
}

private void buildIndex() {
        if (monitorModel.getMessageIndex() == null) {
            // the index, every columns create an index
            ArrayList<HashMap<String, TreeSet<Integer>>> messageIndex = new ArrayList<>(filterableColumn.length);
            for (int i = filterableColumn.length; i >= 0; i--) {
                // key -> string,   value -> treeset, the row wich contains the key
                HashMap<String, TreeSet<Integer>> hash = new HashMap<>();
                messageIndex.add(hash);
            }
            // create index for every column
            for (int i = monitorModel.getParser().getMyMessages().getMessages().size() - 1; i >= 0; --i) {
                TreeSet<Integer> tempList;

                for (int j = 0; j < filterableColumn.length; j++) {
                    String value  = StringPool.getString(getValueAt(i, j).toString());
                    if (!messageIndex.get(j).containsKey(value)) {
                        tempList = new TreeSet<>();
                        messageIndex.get(j).put(value, tempList);
                    } else {
                        tempList = messageIndex.get(j).get(value);
                    }

                    tempList.add(i);
                }
            }
            monitorModel.setMessageIndex(messageIndex);
        }
    }

Answer 1:

您可能要检查你的内存堆在一个分析器。 我的猜测是,内存消耗主要不是在字符串存储,但在许多TreeSet<Integer>实例。 如果是这样,则可以通过使用基本数组相当优化( int[] short[]byte[]这取决于要存储的整数值的实际大小)。 或者你可以寻找到一个原始集合类型,如提供的FastUtil或特罗韦 。

如果您发现该字符串存储是有问题的,我会假设你想扩展您的应用程序超过50万串,或特别紧内存限制需要你去复制甚至短字符串。

作为开发说, String.intern()将重复数据删除字符串为您服务。 一个警告,但是-在Oracle和OpenJDK的虚拟机String.intern()将这些字符串存储在VM永久代,这样它们就不会被垃圾收集在未来。 这是适当的(和有益的),如果:

  1. 要存储的字符串不整个虚拟机的生命改变(例如,如果你在启动时的静态列表读取,并用它在你的应用程序的生命)。
  2. 该字符串你需要舒适适合存储在VM永久代(有足够的空间用于类加载和其他消费者的PermGen的)。 更新:见下文。

如果任这些条件是假的,你可能是正确的,以建立一个自定义池。 但是,我的建议是,你考虑一个简单HashMap替代的WeakHashMap您目前使用。 你可能不希望这些值是垃圾收集,而他们在你的缓存,并WeakHashMap添加了一个间接另一个水平(以及相关的对象指针),进一步提高了内存消耗。

更新:我听说JDK 7店实习字符串( String.intern()在主堆,不烫发根,作为较早的JDK一样。 这使得String.intern()风险较小,如果你正在使用JDK 7。



Answer 2:

无需拿出一个自定义池。 只要使用String.intern()



文章来源: Java collection and memory optimization