Java 列表在地图中给出<;关键,价值观>;作为值,如何找到一个或多个具有最大列表大小的键

Java 列表在地图中给出<;关键,价值观>;作为值,如何找到一个或多个具有最大列表大小的键,java,performance,dictionary,iteration,java-streams,Java,Performance,Dictionary,Iteration,Java Streams,我已经编写了一个返回映射的方法。 地图的结构如下: Map<String, List<String>> map; Map; 地图可以包含1000多个键,每个键可以包含10000多个大小的列表。 我想得到那些具有最大列表大小的键。如果可能的话,有什么方法可以在最短的时间内得到结果吗?如果性能是一个优先事项,请忘记性能,使用本地方法,使用简单的for循环迭代 String maxKey; int maxSize = -1; for (Entry<String, L

我已经编写了一个返回映射的方法。 地图的结构如下:

Map<String, List<String>> map;
Map;
地图可以包含1000多个键,每个键可以包含10000多个大小的列表。
我想得到那些具有最大列表大小的键。如果可能的话,有什么方法可以在最短的时间内得到结果吗?

如果性能是一个优先事项,请忘记性能,使用本地方法,使用简单的
for循环
迭代

String maxKey;
int maxSize = -1;

for (Entry<String, List<String>> list: map.entrySet()) {
    int size = list.getValue().size();
    if (size  > maxSize) {
        maxKey = list.getKey();
        maxSize = size;
    }
}

使用streams,您可以组合一个解决方案,迭代地图的所有条目,获取每个列表的大小,以最终提供具有“max”大小列表的键。或者你按照尼古拉斯回答中的建议,实施“老派”方法

问题是:如果您需要经常这样做,它仍然可能会变成一个性能问题。从这个角度来看,您应该问问自己,数据的这种“布局”是否真的是您所需要的

意思:你可以使用树形图,并给它一个特殊的比较器,而不是使用地图。然后,根据这些列表的长度对地图条目进行排序。然后你只需选择“第一个”条目,你就获得了赢家。这里的缺点是比较器只对进入映射的键起作用,因此您可能需要一些特殊的“包装类”,其中键知道列表大小。这很难看

或者,您可以创建一个特殊的“包装贴图”,该贴图内部包含两个贴图:

  • 将列表大小映射到“真实”映射键的
    TreeMap
  • 保存实际数据的真实地图

使用java8流过滤功能:

Map <String, List<String>> map = new HashMap<>();

Map <String, List<String>> filteredMap = map.entrySet().stream()
                    .filter(stringListEntry -> stringListEntry.getValue().size() > 100)
                    .limit(10)
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Map Map=newhashmap();
Map filteredMap=Map.entrySet().stream()
.filter(stringListEntry->stringListEntry.getValue().size()>100)
.限额(10)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));

`

按照值列表的大小对条目进行分组,数据结构可帮助您找到最大的键:

TreeMap<Integer, List<Entry<String, List<String>>>> collect =
    map.entrySet().stream()
        .collect(groupingBy(e -> e.getValue().size(), TreeMap::new, toList()));
当然,您也可以在不使用流的情况下执行此操作,并且不保留所有小于最大值的条目:

List<Map.Entry<String, List<String>>> largestEntries = new ArrayList<>();
// Don't need both this and largestEntries;
// just adding to show how you'd only get keys.
List<String> largestKeys = new ArrayList<>();  
int largestSize = Integer.MIN_VALUE;

for (Map.Entry<String, List<String>> entry : map.entrySet()) {
  if (entry.getValue().size() > largestSize) {
    largestEntries.clear();
    largestEntries.add(entry);
    largestKeys.add(entry.getKey());
    largestSize = entry.getValue().size();
  } else if (entry.getValue().size() == largestSize) {
    largestEntries.add(entry);
    largestKeys.add(entry.getKey());
  }
}
List largestEntries=new ArrayList();
//不需要这个和最大的条目;
//只是增加一点来说明你是如何得到钥匙的。
List largestKeys=new ArrayList();
int largestSize=Integer.MIN_值;
对于(Map.Entry:Map.entrySet()){
if(entry.getValue().size()>largestSize){
最大的条目。清除();
最大条目。添加(条目);
添加(entry.getKey());
largestSize=entry.getValue().size();
}else if(entry.getValue().size()==largestSize){
最大条目。添加(条目);
添加(entry.getKey());
}
}

您仍然可以使用
JavaSteam
API:

  Map<String, List<Integer>> map = Map.of(
                                        "a",List.of(1,2),
                                        "b",List.of(3,4,5,6),
                                        "c",List.of(7,8,9)
                                   );
Map Map=Map.of(
“a”,第(1,2)项清单,
“b”,第(3,4,5,6)项清单,
“c”,第(7、8、9)项清单
);
具有最大列表大小的条目:

Optional<Map.Entry<String, List<Integer>>> max = map.entrySet()
                    .stream()
                    .max(Comparator.comparingInt(value -> value.getValue().size()));
Integer maxSize = max.get().getValue().size();
Map<String, List<Integer>> maxMap = map
        .entrySet()
        .stream()
        .filter(entry -> entry.getValue().size() == maxSize)
        .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
Optional max=map.entrySet()
.stream()
.max(Comparator.comparingit(value->value.getValue().size());
具有最大列表大小的条目的映射:

Optional<Map.Entry<String, List<Integer>>> max = map.entrySet()
                    .stream()
                    .max(Comparator.comparingInt(value -> value.getValue().size()));
Integer maxSize = max.get().getValue().size();
Map<String, List<Integer>> maxMap = map
        .entrySet()
        .stream()
        .filter(entry -> entry.getValue().size() == maxSize)
        .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
Integer maxSize=max.get().getValue().size();
maxMap=Map
.entrySet()
.stream()
.filter(条目->条目.getValue().size()==maxSize)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
最后,您可以在LinkedHashMap中对结果进行排序和存储:

LinkedHashMap<String, List<Integer>> sortedMap = map
        .entrySet()
        .stream()
        .sorted(Comparator.comparingInt(value -> value.getValue().size()))
        .collect(
                Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (u, v) -> {
                            throw new IllegalStateException(String.format("Duplicate key %s", u));
                        }, 
                        LinkedHashMap::new 
                )
        );
LinkedHashMap sortedMap=map
.entrySet()
.stream()
.sorted(Comparator.comparingit(value->value.getValue().size())
.收集(
汤姆(
Map.Entry::getKey,
Map.Entry::getValue,
(u,v)->{
抛出新的IllegalStateException(String.format(“重复键%s”,u));
}, 
LinkedHashMap::新建
)
);

要获取指向最大列表的一个键吗?是什么阻碍了您迭代映射并调用列表的.size()方法?只要比较一下这些,就可以了。如果性能是最重要的,那么就应该使用不同的数据结构。。。尽管如此,你还是得到了我的投票,因为我花了时间写下了一些代码。请注意,OP要求所有匹配列表最大的密钥。可能有多个键具有大小列表,例如15000。@GhostCat:这是一个很好的观点!我希望数据已经映射到
Map
结构,所以我使用了它。当然,数据的来源很重要。“然后根据这些列表的长度对地图条目进行排序”树形图比较器对键进行排序,而不是条目或值。我不认为OP要求10个条目的地图大小大于100。OP要求所有匹配值最大的键。它足够接近,您可以使用上面的键来实现所需。您可以用maxSize替换100,这可以用类似的方法轻松计算,您也可以用fintFirst替换limit,这样您将经历两次。性能方面不是很好。大多数时候,你应该首先考虑可读性,如果没有问题,就不要担心性能