我写了一个返回地图的方法。 地图的结构是:
Process: com.example.app, PID: 14212
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.SCAN_RESULTS flg=0x4000010 } in com..app.MainActivity$WifiScanReceiver@424b88a0
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:773)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5756)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.StringIndexOutOfBoundsException: length=0; index=5
at java.lang.String.indexAndLength(String.java:584)
at java.lang.String.substring(String.java:1449)
at com.example.app.MainActivity$WifiScanReceiver.onReceive(MainActivity.java:83)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:763)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5756)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
该地图可以包含1000个以上的键,每个键可以包含大小超过10000个的列表。 我想获得那些具有最大列表大小的键。如果可能的话,有什么方法可以在最短的时间内得到结果?
答案 0 :(得分:3)
使用流,您可以组合一个解决方案,该解决方案可迭代地图的所有条目,获取每个列表的 size ,以最终提供具有“ max”大小列表的键。或者,您可以按照尼古拉斯(Nikolas)的回答中的建议,实施这种“守旧派”方法。
问题在于:如果您需要经常执行此操作,则仍然可能会导致性能问题。从这种角度来看,您应该问自己:数据的这种“布局”是否真的是您的需要。
含义:您可以使用TreeMap并给它一个特殊的比较器,而不是使用Map。然后,这些地图会根据这些列表的长度对其进行排序。然后,您只需选择“第一个”条目,就可以赢得赢家。这里的缺点是比较器仅对进入映射的键起作用,因此您可能需要一些特殊的“包装类”,其中键知道列表的大小。真丑。
或者,您可以创建一个特殊的“包装图”,内部包含两个图:
TreeMap<Integer, String>
Map<String, List<String>>
。答案 1 :(得分:2)
如果将性能放在首位,请忘记java-streams并通过简单的for-loop
迭代使用本机方法。
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;
}
}
如果要存储最大数量的所有密钥,请将它们存储到Set<String>
并将条件替换为:
int size = list.getValue().size();
if (size == maxSize) {
maxKeySet.add(list.getKey());
}
if (size > maxSize) {
maxKeySet.clear();
maxKeySet.add(list.getKey());
maxSize = size;
}
答案 2 :(得分:0)
使用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));
`
答案 3 :(得分:0)
按值列表的大小对条目进行分组,采用有助于您找到最大键的数据结构:
TreeMap<Integer, List<Entry<String, List<String>>>> collect =
map.entrySet().stream()
.collect(groupingBy(e -> e.getValue().size(), TreeMap::new, toList()));
(您可以使用mapping(Map.Entry::getKey, toList())
而不是toList()
来获取密钥)。
然后使用以下命令获取最大尺寸的条目:
List<Map.Entry<String, List<String>>> largestEntries =
grouped.lastEntry().getValue();
当然,您也可以在没有流的情况下执行此操作,并且无需保留所有小于最大条目的条目:
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());
}
}
答案 4 :(得分:0)
您仍然可以使用java-steam
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)
);
具有最大列表大小的条目:
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));
或者最后,您可以对Map进行排序并将结果存储在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
)
);