Есть ли более эффективный способ сделать HashMap со счетчиком из ArrayList? - PullRequest
0 голосов
/ 28 мая 2018

У меня есть метод, который позволяет мне создать HashMap из ArrayList, получив объект AirbnbListing, а затем сравнивая имя окрестности с любыми ключами в HashMap.Если его нет в hashmap, я добавляю его со счетчиком, начинающимся с 1, если он уже существует, я увеличиваю счетчик.

Есть ли более эффективный способ сделать это, вот мой код:

    public HashMap<String, Integer> sortHousesInNbrhood(ArrayList<AirbnbListing> priceRangeListing) {
    HashMap<String, Integer> housesInNbrhood = new HashMap<>();
    for (AirbnbListing listing : priceRangeListing) {
        if (housesInNbrhood.isEmpty()) {
            housesInNbrhood.put(listing.getNeighbourhood(), 1); 
        } else if (housesInNbrhood.containsKey(listing.getNeighbourhood())) {
            housesInNbrhood.replace(listing.getNeighbourhood(), housesInNbrhood.get(listing.getNeighbourhood()) + 1);
        } else {
            housesInNbrhood.put(listing.getNeighbourhood(),1); 
        }
    }

    return housesInNbrhood;
}

Ответы [ 3 ]

0 голосов
/ 28 мая 2018
public HashMap<String, Integer> sortHousesInNbrhood(ArrayList<AirbnbListing> priceRangeListing) {
    HashMap<String, Integer> housesInNbrhood = new HashMap<>();
    for (AirbnbListing listing : priceRangeListing) {
         housesInNbrhood.compute(listing.getNeighbourhood(), (k, v) -> (v == null) ? 1 : v + 1);
    }

    return housesInNbrhood;
}
0 голосов
/ 28 мая 2018

Multiset - это структуры данных, которые специализируются для отслеживания того, сколько раз объект встречается в наборе.Они идеально подходят для вашей задачи!

Они недоступны в стандартных библиотеках Java, но они есть в библиотеке Guava.

Я предлагаю заменить HashMap в качестве возвратазначение вашего метода с Multiset.В этом случае читателям будет более понятно, что в нем содержится.

При таком решении код выглядит следующим образом:

public Multiset<String> sortHousesInNbrhood(List<AirbnbListing> priceRangeListing) {
    Multiset<String> housesInNbrhood = TreeMultiset.create();
    // Multimap automatically counts the number of times an object have been added
    priceRangeListing.forEach(list -> housesInNbrhood.add(list.getNeighbourhood()));
    return housesInNbrhood;
}

// Use the multiset like this:
public void useMultiset(List<AirbnbListing> priceRangeListing) {
    Multiset<String> s = sortHousesInNbrhood(priceRangeListing);
    System.out.println("Houses in Bagdad:" + s.count("Bagdad"));

    System.out.println("All counts: ");
    for (Entry<String> e : s.entrySet()) {
        System.out.println(e.getElement() + ": " + e.getCount());
    }
}

Если вам нужно вернуть HashMapзатем вы можете построить его из Multiset следующим образом:

public Map<String, Integer> sortHousesInNbrhood_2(List<AirbnbListing> priceRangeListing) {
    Multiset<String> housesInNbrhood = TreeMultiset.create();
    priceRangeListing.forEach(list -> housesInNbrhood.add(list.getNeighbourhood()));
    return housesInNbrhood.entrySet().stream().collect(toMap(Entry::getElement, Entry::getCount));
}

Мультисеты и мультикарты - некоторые из моих любимых структур данных.Так удобно!

0 голосов
/ 28 мая 2018

Используйте коллектор groupingBy с counting в качестве выходного коллектора:

priceRangeListing.stream()
                 .collect(groupingBy(AirbnbListing::getNeighbourhood, counting()));

Обратите внимание, что приведенное выше даст Map<String, Long>, ноесли вы действительно хотите Map<String, Integer>, используйте коллектор summingInt в качестве нисходящего потока:

priceRangeListing.stream()
       .collect(groupingBy(AirbnbListing::getNeighbourhood, summingInt(e -> 1)));
...