Получение значения с карты - PullRequest
       11

Получение значения с карты

1 голос
/ 22 сентября 2011

Мне нужно получить одну информацию из коллекции (get() вызовов в диапазоне 100 КБ для обработки одного файла).

public class DemoCollection {

    private Map<GroupCriteria, GroupData> collectionHolder = new ConcurrentHashMap<GroupCriteria, GroupData>();

    /**
     * 
     * @param groupCriteria
     *            GroupCriteria
     * @return GroupData
     */
    public GroupData getGroupForGroupingCriteriaOne(GroupCriteria groupCriteria) {
        GroupData groupData = null;
        if (collectionHolder.containsKey(groupCriteria)) {
            groupData = collectionHolder.get(groupCriteria);
        } else {
            // Get from database
        }
        return groupData;
    }

    /**
     * 
     * @param groupCriteria
     *            GroupCriteria
     * @return GroupData
     */
    public GroupData getGroupForGroupingCriteriaTwo(GroupCriteria groupCriteria) {
        GroupData groupData = null;
        if ((groupData = collectionHolder.get(groupCriteria)) == null) {
            // GEt from database
        }
        return groupData;
    }
}

Какова наилучшая практика в этом отношении?Подход один (getGroupForGroupingCriteriaOne), два (getGroupForGroupingCriteriaTwo) или ни один?

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

Не могли бы вы дать совет?

Ответы [ 5 ]

2 голосов
/ 22 сентября 2011

getGroupForGroupingCriteriaTwo - это путь, потому что вы просите карту выполнить поиск ключа один раз, а не два.

1 голос
/ 22 сентября 2011

В целом я согласен с ответами о том, что getGroupForGroupingCriteriaTwo лучше, поскольку он обращается к карте только один раз, однако ваше беспокойство о том, что, поскольку карта содержит 100 тыс. Элементов, время доступа будет высоким, оно неуместно.

Вы используете ConcurrentHashMap, поиск HashMap имеет сложность вычислений O(1), что означает, что независимо от размера данных эти вызовы будут возвращаться в постоянное время.

Эта оптимизация не улучшит производительность. Если вы действительно заинтересованы в повышении производительности, рассмотрите возможность использования подходящей инфраструктуры кэширования.

1 голос
/ 22 сентября 2011

Рассмотрите возможность использования MapMaker от Guava :

private ConcurrentMap<GroupCriteria, GroupData> collectionHolder = new MapMaker()
        .makeComputingMap(
           new Function<GroupCriteria, GroupData>() {
              @Override
              public GroupData apply(GroupCriteria key) {
                 //get from database and return
              }
        });

Это ConcurrentMap будет обрабатывать все одновременные запросы для вас. См. MapMaker документацию для списка всех настраиваемых функций созданной карты.

1 голос
/ 22 сентября 2011

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

public GroupData getGroupForGroupingCriteriaThree(GroupCriteria groupCriteria) {
    GroupData groupData = collectionHolder.get(groupCriteria);

    return groupData != null ? groupData : callGetDataFromDB();
}
1 голос
/ 22 сентября 2011

getGroupForGroupingCriteriaTwo выглядит вполне разумно.getGroupForGroupingCriteriaOne делает два поиска на карте - один для поиска «ключа», а другой для извлечения значения.

Однако я надеюсь, что после fetching from database вы поместите объект на карту(в качестве кеша), чтобы то же самое можно было использовать с карты в следующий раз, а не запрашивать.

...