Оптимизируйте использование памяти набора Строк в Java

Установите высоту кубов в px, а не в %, например :

height: 20px;

См. Обновленный код:: 113

9
задан Kishnan 7 April 2009 в 13:16
поделиться

7 ответов

Не используйте String.intern (были различные проблемы памяти, связанные с этим в течение лет). вместо этого, создайте свой собственный кэш, подобный String.intern. в основном, Вы хотите Карту, где каждый контурные карты к себе. затем, прежде, чем кэшировать любую строку, Вы "интернируете" его:

private Map<String,WeakReference<String>> myInternMap = new WeakHashMap<String,,WeakReference<String>>();
public String intern(String value) {
  synchronized(myInternMap) {
    WeakReference<String> curRef = myInternMap.get(value);
    String curValue = ((curRef != null) ? curRef.get() : null);
    if(curValue != null) {
      return curValue;
    }

    myInternMap.put(value, new WeakReference<String>(value));
    return value;
  }
}

отметьте, Вы используете weakreferences для ключей и значений так, чтобы Вы не сохраняли ссылки для строк, которые Вы больше не используете.

10
ответ дан 4 December 2019 в 08:34
поделиться

String.intern () поможет Вам здесь (скорее всего). Это разрешит несколько экземпляров той же строки вниз к одной копии.

Править: Я предположил, что это, 'скорее всего', поможет. В каком сценарии будут он нет? Интернирование строк будет иметь эффект хранения тех интернированных строковых представлений постоянно. Если проблемная область является одноразовым процессом, это не может быть проблемой. Если это - длительный процесс (такой как веб-приложение) затем, у Вас может быть проблема.

Я смущался бы говорить никогда интернирование использования (я буду, hesistate для высказывания никогда ничего не делают). Однако существуют сценарии, где это не идеально.

9
ответ дан 4 December 2019 в 08:34
поделиться

String.intern очевидный выбор, как говорит Brian. Но если Вы не хотите интернировать через всю Строку в памяти, можно использовать Набор, чтобы увидеть в первый раз, если значение присутствует. Здесь не протестировал код. Необходимо будет разработать удаление из обратной карты при удалении из основного

  class Map2<K, V> implements Map<K, V>
  {
    Map<K, V> _map = Maps.newHashMap();
    Set<V, V> _rev = Maps.newHashMap();

    V put(K k, V v) {
      if (_rev.containsKey(v)) {
        V prev = _rev.get(v);
        return _map.put(k, prev);
      } else {
        _rev.put(v, v);
        return _map.put(k,v);
      }
   }
4
ответ дан 4 December 2019 в 08:34
поделиться

Это несколько зависит от того, как Вы создаете String.

Один возможный путь состоит в том, чтобы использовать TreeSet это использует a Comparator это может выдержать сравнение существующий Strings и источник Вашего нового String. Использовать SortedSet.tailSet и Iterator найти существующее String. Или альтернативно NavigableSet.ceiling/floor или a TreeMap с подобной установкой.

Я записал запись блога о другой технике для кэширования неизменных объектов (в особенности Строки), но это более подходит для меньших объектов.

String.intern имеет проблемы производительности.

1
ответ дан 4 December 2019 в 08:34
поделиться

Согласованный с другими при не использовании String.intern (): после того как Вы поместили строку там, она никогда не будет уходить. Обратитесь к ранним изменениям Xerces для того, почему это - плохая идея.

Лучшее решение состоит в том, чтобы использовать WeakHashMap, перенося значение в WeakReference:

private Map<String,WeakReference<String>> _map 
    = new WeakHashMap<String,WeakReference<String>>();

public synchronized String intern(String str)
{
    WeakReference<String> ref = _map.get(str);
    String s2 = (ref != null) ? ref.get() : null;
    if (s2 != null)
        return s2;
    str = new String(str);
    _map.put(str, new WeakReference(str));
    return str;
}

Этот код от статьи, которую я написал о ссылочных объектах Java. Вы найдете объяснение там.

Править: потребность создать новую строку здесь (и я обновлю статью), потому что оригинал мог бы быть подстрокой намного большего символьного массива. Я думал, что это было зафиксировано вокруг JDK 1.3, но по-видимому не (по крайней мере, не в 1,5).

1
ответ дан 4 December 2019 в 08:34
поделиться

Вы могли сжать строки. Строка 30K должна получить хорошую степень сжатия. Я записал взлом для сжатия большой Строки как осуществления, но Вы могли использовать байт [] сжатых данных для хранения Строки.

30K символьная строка будет использовать приблизительно 60 КБ (2 байта за символ), поэтому даже использующие getBytes (), вероятно, будет улучшение.

0
ответ дан 4 December 2019 в 08:34
поделиться

Вам на самом деле нужны Строки, или Вам просто нужен какой-либо старый CharSequence? В противном случае затем рассмотрите реализацию "компактного" CharSequence, такого как тот, который я предлагаю в ссылке.

0
ответ дан 4 December 2019 в 08:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: