Я хочу использовать String[] журналов с подробным описанием пользователей, которые подключались к веб-сайту, чтобы распечатать в порядке убывания количество подключений каждого пользователя. Каждый журнал содержит некоторую информацию, но уникальный идентификатор пользователя всегда находится в пределах первого индекса массива.
Я пытаюсь просмотреть массив за время O(N), подсчитать, сколько раз каждый пользователь подключался, добавляя их в HashMap, а затем распечатывать подключенных пользователей в порядке убывания в зависимости от того, сколько раз они подключались. Как это может быть сделано? Я готов переключить всю свою реализацию, если есть более простой способ отслеживать количество вхождений в String[]. Я прикрепил пример ниже:
// Connection logs in the form [Username, Location, time]
String[] logs = {
"name1,Chicago,8pm",
"name2,New York,6pm",
"name3,Los Angeles,2am",
"name1,Chicago,3pm",
"name1,Chicago,12pm",
"name4,Miami,3pm"
"name4,Miami,6pm"
};
printConnections(logs);
/* Desired output:
name1: 3
name2: 2
name4: 2
name3: 1
*/
public static void printConnections(String[] connections){
HashMap<String, Integer> hashmap = new HashMap<String, Integer>();
for (String log : connections){
String name = log.split(",")[0];
if (hashmap.containsKey(name)){
hashmap.replace(name, hashmap.get(name) + 1);
}
else{
hashmap.put(name, 1);
}
}
// Print all key/values in descending order of value
}
Либо действительно, я просто ищу решение этой проблемы. Меня спросили во время стартового интервью, и я испортил это, поэтому я надеюсь извлечь из этого уроки в будущем, но я изо всех сил пытаюсь придумать элегантное решение.
Отвечает ли это на ваш вопрос? Как отсортировать LinkedHashMap по значению в порядке убывания в потоке Java?
TLDR:
// Print all key/values in descending order of value
var sorted = hashmap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()));
sorted.forEach(pair->System.out.println(pair.getKey() + ": " + pair.getValue()));
Выход:
name1: 3
name4: 2
name3: 1
name2: 1
Как это устроено?
hashmap.entrySet()
вернет набор Map.Entry
объектов
.stream()
вернет поток этих объектов
.sorted()
сортирует поток по значению объектов Map.Entry
Полный:
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void printConnections(String[] connections) {
HashMap<String, Integer> hashmap = new HashMap<String, Integer>();
for (String log : connections) {
String name = log.split(",")[0];
if (hashmap.containsKey(name)) {
hashmap.replace(name, hashmap.get(name) + 1);
} else {
hashmap.put(name, 1);
}
}
// Print all key/values in descending order of value
var sorted = hashmap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()));
sorted.forEach(pair->System.out.println(pair.getKey() + ": " + pair.getValue()));
}
public static void main(String[] args) {
// Connection logs in the form [Username, Location, time]
String[] logs = {
"name1,Chicago,8pm",
"name2,New York,6pm",
"name3,Los Angeles,2am",
"name1,Chicago,3pm",
"name1,Chicago,12pm",
"name4,Miami,3pm",
"name4,Miami,6pm"
};
printConnections(logs);
}
}
Прежде всего, я предполагаю, что под O(n) вы подразумеваете O(n), где n = количество уникальных пользователей (т.е. hashmap.keySet().size()
). К сожалению, ваша проблема связана с сортировкой, которая в лучшем случае является сложностью O (n * log (n)), поэтому я не думаю, что это возможно сделать за время O (n). Тем не менее, у меня есть код, чтобы выполнить работу:
ArrayList<Entry<String, Integer>> logList = new ArrayList<>(hashMap.entrySet());
Collections.sort(logList, new Comparator<Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return o2.getKey().compareTo(o1.getKey());
}
});
Вы должны использовать API потока Java для решения этой проблемы.
hashmap.entrySet()
.stream()
// "Map.Entry.comparingByValue())" is convert HashMap value into ascending order by default
// "Collections.reverseOrder()" is convert HashMap value into reverse of ascending order(descending)
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
// print the hashmap
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
Итак, что за вопрос точный? Вы хотите знать, как сортировать HashMap по значению? Или вы просите кого-нибудь разработать решение вашей проблемы с журналированием?