在hashmap中存储String数据类型时是否有任何减少内存使用的技巧?

时间:2012-10-24 17:27:53

标签: java string hashmap

我需要在地图中存储价值对(单词和数字)。

我正在尝试使用来自Trove库的TObjectIntHashMap并使用char[]作为密钥,因为我需要最小化内存使用量。但是使用这种方法,当我使用get()方法时,我无法获得该值 我想我不能使用原始字符数组存储在Map中,因为哈希码问题。

我尝试使用TCharArrayList,但这也需要很多记忆 我在另一个与我的目的相似的stackoverflow问题中读到并建议使用TLongIntHashMap,在长数据类型中存储String字的编码值。在这种情况下,我的单词可能包含拉丁字符或维基百科集合中出现的各种其他字符,我不知道Long是否足以进行编码。

我尝试使用Trie数据结构来存储它,但我也需要考虑我的性能,并选择最适合内存使用和性能。

您对此问题有任何想法或建议吗?

2 个答案:

答案 0 :(得分:3)

听起来,存储数据最紧凑的方法是使用byte[]中编码的UTF-8或类似内容。您可以将它包装在您自己的类中,也可以编写自己的HashMap,它允许byte []作为键。

我会重新考虑花多少时间来节省一些记忆。如果您正在谈论PC或服务器,那么您需要以最低工资保存1 GB的工作时间,因此如果您只想节省100 MB,那么大约需要6分钟,包括测试。

答案 1 :(得分:0)

编写自己的实现CharSequence的类,并编写自己的equals()hashcode()实现。该实现还将预先分配大型共享char[]存储,并一次使用它的位。 (你绝对可以将@Peter Lawrey的优秀建议纳入其中,并使用byte[]存储。)

还有机会使用LRU缓存执行'soft intern()'。我已经注意到了缓存的位置。

这是我的意思的简单演示。请注意,如果您需要大量并发写入,可以尝试改进下面的锁定方案......

public final class CompactString implements CharSequence {
  private final char[] _data;
  private final int _offset;
  private final int _length;
  private final int _hashCode;

  private static final Object _lock = new Object();
  private static char[] _storage;
  private static int _nextIndex;

  private static final int LENGTH_THRESHOLD = 128;

  private CompactString(char[] data, int offset, int length, int hashCode) {
    _data = data; _offset = offset; _length = length; _hashCode = hashCode;
  }

  private static final CompactString EMPTY = new CompactString(new char[0], 0, 0, "".hashCode());

  private static allocateStorage() {
    synchronized (_lock) {
      _storage = new char[1024];
      _nextIndex = 0;
    }
  }

  private static CompactString storeInShared(String value) {
    synchronized (_lock) {
      if (_nextIndex + value.length() > _storage.length) {
        allocateStorage();
      }
      int start = _nextIndex; 
      // You would need to change this loop and length to do UTF encoding.
      for (int i = 0; i < value.length(); ++i) {
        _storage[_nextIndex++] = value.charAt(i);
      }
      return new CompactString(_storage, start, value.length(), value.hashCode());
    }
  }

  static {
    allocateStorage();
  }

  public static CompactString valueOf(String value) {
    // You can implement a soft .intern-like solution here.
    if (value == null) {
      return null;
    } else if (value.length() == 0) {
      return EMPTY;
    } else if (value.length() > LENGTH_THRESHOLD) {
      // You would need to change .toCharArray() and length to do UTF encoding.
      return new CompactString(value.toCharArray(), 0, value.length(), value.hashCode());
    } else {
      return storeInShared(value);
    }
  }

  // left to reader: implement equals etc.
}