在地图中获取3个最大值

发布于 2025-02-07 22:43:55 字数 828 浏览 1 评论 0原文

我正在存储lastbyfirst变量的信息。

{Peter=[Leigh], George=[Barron, Trickett,Evans], 
 Paul-Courtenay=[Hyu], Ryan=[Smith], Toby=[Geller, Williams], 
 Simon=[Bush, Milosic, Quarterman,Brown]}

我如何打印第一个3,该出现最多,也是popereance的数量。

我想列出3个值最多的那些。在lastByFirst中包含类似的内容。我想以这种方式打印:

Simon: 4  
George: 3  
Toby:2
Map<String, List<String>> lastByFirst = PeopleProcessor.lastnamesByFirstname(PeopleSetup.people);

我的尝试就是这样:

var store = lastByFirst.entrySet()
    .stream()
    .collect( Collectors.groupingBy(Person::getLastName,
                Collectors.counting())
    .toString();

Store应该与

Simon: 4  
George: 3  
Toby:2

I'm storing information of the lastByFirst variable.

{Peter=[Leigh], George=[Barron, Trickett,Evans], 
 Paul-Courtenay=[Hyu], Ryan=[Smith], Toby=[Geller, Williams], 
 Simon=[Bush, Milosic, Quarterman,Brown]}

How can I print the first 3 which appeared the most and also the number of appereance.

I would like to list those which 3 value appeared the most. In the lastByFirst contains something like that. I would like to print in this way:

Simon: 4  
George: 3  
Toby:2
Map<String, List<String>> lastByFirst = PeopleProcessor.lastnamesByFirstname(PeopleSetup.people);

My attempt was something like that:

var store = lastByFirst.entrySet()
    .stream()
    .collect( Collectors.groupingBy(Person::getLastName,
                Collectors.counting())
    .toString();

store should be equal with

Simon: 4  
George: 3  
Toby:2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一身骄傲 2025-02-14 22:43:55

这是首先将列表地图转换为列表尺寸的地图,然后选择前三个尺寸的地图:

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Demo {
    public static void main(String[] args) {
        Map<String, List<String>> lastByFirst =
            Map.of("Peter", List.of("Leigh"), "George", List.of("Barron", "Trickett", "Evans"),
                   "Paul-Courtenay", List.of("Hyu"), "Ryan", List.of("Smith"),
                   "Toby", List.of("Geller", "Williams"), "Simon", List.of("Bush", "Milosic", "Quaterman", "Brown"));
        List<Map.Entry<String, Integer>> topThree =
            lastByFirst.entrySet().stream()
            .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> e.getValue().size()))
            .entrySet()
            .stream()
            .sorted(Comparator.<Map.Entry<String, Integer>, Integer>comparing(Map.Entry::getValue).reversed())
            .limit(3)
            .collect(Collectors.toList());
        System.out.println(topThree);
    }
}

Here's one that first converts the map of lists to a map of the sizes of the list, and then picks the top three such sizes:

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Demo {
    public static void main(String[] args) {
        Map<String, List<String>> lastByFirst =
            Map.of("Peter", List.of("Leigh"), "George", List.of("Barron", "Trickett", "Evans"),
                   "Paul-Courtenay", List.of("Hyu"), "Ryan", List.of("Smith"),
                   "Toby", List.of("Geller", "Williams"), "Simon", List.of("Bush", "Milosic", "Quaterman", "Brown"));
        List<Map.Entry<String, Integer>> topThree =
            lastByFirst.entrySet().stream()
            .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> e.getValue().size()))
            .entrySet()
            .stream()
            .sorted(Comparator.<Map.Entry<String, Integer>, Integer>comparing(Map.Entry::getValue).reversed())
            .limit(3)
            .collect(Collectors.toList());
        System.out.println(topThree);
    }
}
浪漫之都 2025-02-14 22:43:55

您可以:

  1. 按尺寸按降序模式
  2. ,选择前三个元素
  3. 降低到一个字符串
//1
List<Map.Entry<String, List<String>>> entryList = lastByFirst.entrySet()
        .stream()
        .sorted((e2, e1) -> Integer.compare(e1.getValue().size(), e2.getValue().size()))
        .toList();
//2
String result = IntStream.range(0, 3)
        .mapToObj(entryList::get)
        .map(e -> String.format("%s: %d\n", e.getKey(), e.getValue().size()))
        .collect(Collectors.joining()); //3

You can:

  1. sort in descending mode by size
  2. select the first three elements
  3. reduce to one string
//1
List<Map.Entry<String, List<String>>> entryList = lastByFirst.entrySet()
        .stream()
        .sorted((e2, e1) -> Integer.compare(e1.getValue().size(), e2.getValue().size()))
        .toList();
//2
String result = IntStream.range(0, 3)
        .mapToObj(entryList::get)
        .map(e -> String.format("%s: %d\n", e.getKey(), e.getValue().size()))
        .collect(Collectors.joining()); //3
生死何惧 2025-02-14 22:43:55

如果您已经有一个由 组成的人的地图,则可以解决在线性中查找3最常见的最常见的问题时间 o(n)。比对整个数据集进行排序更快。

如果不是选择3最常见的名字最常见的是m,那么时间复杂性将为 o( n + m * log m)对于m的小值,将接近线性时间)。

要使用流实施它,我们可以使用自定义比较器,可以使用静态方法

作为收集器的一个可变容器,我们可以使用treemap自然顺序中排序,其中 key 将代表具有相同名字的人,而 value 将是一个名字本身。

为了仅保留m最常见的名称,我们需要跟踪treemap的大小,并且当它超过时,我们必须删除第一个条目(即具有最低键的条目)。

public static <K, V> Collector<Map.Entry<K, List<V>>, ?, NavigableMap<Integer, K>>
                                                        getEntryCollector(int size) {
    return Collector.of(
        TreeMap::new,
        (NavigableMap<Integer, K> map, Map.Entry<K, List<V>> entry) -> {
            if (map.size() < size || map.firstKey() < entry.getValue().size()) {  // the container hasn't reached the maximum size of the frequency of the offered name is higher than the lowest existing frequency
                map.put(entry.getValue().size(), entry.getKey());
            }
            if (map.size() > size) map.remove(map.firstKey()); // the size of the container has been exceeded
        },
        (NavigableMap<Integer, K> left, NavigableMap<Integer, K> right) -> { // merging the two containers with partial results obtained during the parallel execution
            left.putAll(right);
            while (left.size() > size) left.remove(left.firstKey());
            return left;
        }
    );
}

main()

public static void main(String args[]) {

    Map<String, List<String>> lastByFirst =
    Map.of("Peter", List.of("Leigh"), "George", List.of("Barron", "Trickett", "Evans"),
    "Paul-Courtenay", List.of("Hyu"), "Ryan", List.of("Smith"), "Toby", List.of("Geller", "Williams"),
    "Simon", List.of("Bush", "Milosic", "Quarterman", "Brown"));

    NavigableMap<Integer, String> nameByFrequency =
        lastByFirst.entrySet().stream()
            .collect(getEntryCollector(3));
    
    nameByFrequency.entrySet().stream() // printing the result, sorting in reversed order applied only for demo purposes
        .sorted(Map.Entry.comparingByKey(Comparator.<Integer>naturalOrder().reversed()))
        .forEach(entry -> System.out.println(entry.getValue() + ": " + entry.getKey()));
}

输出:

Simon: 4
George: 3
Toby: 2

a链接在线演示

If you already have a map of people grouped by first name, you can address the problem of finding the 3 most frequent first names in a linear time O(n). Which is faster than sorting the whole data set.

If instead of picking 3 most frequent first names it would be generalized to m most frequent, then the time complexity would be O(n + m * log m) (which for small values of m would be close to linear time).

To implement it using streams, we can utilize a custom comparator, which can be created using the static method Collector.of().

As a mutable container of the collector, we can use a TreeMap sorted in the natural order, where the key would represent the of people having the same first name and the value would be a first name itself.

In order to retain only m most frequent names we need to track the size of the TreeMap and when it gets exceeded we have to remove the first entry (i.e. an entry having the lowest key).

public static <K, V> Collector<Map.Entry<K, List<V>>, ?, NavigableMap<Integer, K>>
                                                        getEntryCollector(int size) {
    return Collector.of(
        TreeMap::new,
        (NavigableMap<Integer, K> map, Map.Entry<K, List<V>> entry) -> {
            if (map.size() < size || map.firstKey() < entry.getValue().size()) {  // the container hasn't reached the maximum size of the frequency of the offered name is higher than the lowest existing frequency
                map.put(entry.getValue().size(), entry.getKey());
            }
            if (map.size() > size) map.remove(map.firstKey()); // the size of the container has been exceeded
        },
        (NavigableMap<Integer, K> left, NavigableMap<Integer, K> right) -> { // merging the two containers with partial results obtained during the parallel execution
            left.putAll(right);
            while (left.size() > size) left.remove(left.firstKey());
            return left;
        }
    );
}

main()

public static void main(String args[]) {

    Map<String, List<String>> lastByFirst =
    Map.of("Peter", List.of("Leigh"), "George", List.of("Barron", "Trickett", "Evans"),
    "Paul-Courtenay", List.of("Hyu"), "Ryan", List.of("Smith"), "Toby", List.of("Geller", "Williams"),
    "Simon", List.of("Bush", "Milosic", "Quarterman", "Brown"));

    NavigableMap<Integer, String> nameByFrequency =
        lastByFirst.entrySet().stream()
            .collect(getEntryCollector(3));
    
    nameByFrequency.entrySet().stream() // printing the result, sorting in reversed order applied only for demo purposes
        .sorted(Map.Entry.comparingByKey(Comparator.<Integer>naturalOrder().reversed()))
        .forEach(entry -> System.out.println(entry.getValue() + ": " + entry.getKey()));
}

Output:

Simon: 4
George: 3
Toby: 2

A link Online Demo

挽梦忆笙歌 2025-02-14 22:43:55

这是 streamex

EntryStream.of(lastByFirst)
        .mapValues(List::size) //
        .reverseSorted(Comparators.comparingByValue())
        .limit(3)
        .toList()
        .forEach(System.out::println);

Here is another solution by StreamEx:

EntryStream.of(lastByFirst)
        .mapValues(List::size) //
        .reverseSorted(Comparators.comparingByValue())
        .limit(3)
        .toList()
        .forEach(System.out::println);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文