Java流:按函数合并映射键
我有一张地图。如果一个键是另一个键的函数,我希望合并键,例如: 如果函数为“prefix”,我希望在映射中给出以下值:Java流:按函数合并映射键,java,java-stream,Java,Java Stream,我有一张地图。如果一个键是另一个键的函数,我希望合并键,例如: 如果函数为“prefix”,我希望在映射中给出以下值: {"123", ["a"]]} {"85", ["a","b"]]} {"8591", ["c"]} 要获取具有这些值的新地图,请执行以下操作: {"123", ["a"]} {"85", ["a","b","c"]} 这个映射“缩减”是作为用户请求的一部分调用的,因此它必须是快速的。我知道我可以做O(n^2),但如果可能的话,我正在寻找更好的并行方法 下面是通过调用get
{"123", ["a"]]}
{"85", ["a","b"]]}
{"8591", ["c"]}
要获取具有这些值的新地图,请执行以下操作:
{"123", ["a"]}
{"85", ["a","b","c"]}
这个映射“缩减”是作为用户请求的一部分调用的,因此它必须是快速的。我知道我可以做O(n^2)
,但如果可能的话,我正在寻找更好的并行方法
下面是通过调用getMatchingKey
函数查找每个键的超级键的代码:
Map<String, Set<String>> result= new HashMap<>();
for (Map.Entry<String, List<String>> entry : input.entrySet()){
String x = getMatchingKey(entry.getKey(), input.keySet());
if (!resultt.containsKey(x)){
resultt.put(x, new HashSet<String>());
}
resultt.get(x).addAll((input.get(x)));
resultt.get(x).addAll((entry.getValue()));
}
函数findsubnetbiggerorequaltime
在所有子网中查找包括子网实例的最大子网
但由于此功能应根据用户请求运行,并且地图包含数十个实体和数万个子网,因此我需要一些快速的功能(内存可用:)我使用了一种方法,首先按字典顺序对子网进行排序。这将把调用
findsubnetbiggerorequaltime
导致的开销从n^2减少到排序算法的复杂性(通常是~nlog(n))。我假设您可以对子网进行排序,因为逻辑应该与findSubnetBiggerOrEqualToMe
中的类似
理想情况下,如果一个子网的所有超级网都是同一组的前缀,那么就可以简单地减少线性时间。示例[1,2,22,222,3]
:
for (int i = 0; i < sortedEntries.size() - 1; i++)
{
Entry<Subnet, Set<String>> subnet = sortedEntries.get(i);
Entry<Subnet, Set<String>> potentialSupernet = sortedEntries.get(i + 1);
if (subnet.getKey().isPrefix(potentialSupernet.getKey()))
{
potentialSupernet.getValue().addAll(subnet.getValue());
sortedEntries.remove(i);
i--;
}
}
这种方法减少n^2的程度取决于独立网络的数量。前缀相等的集合越小,运行时的平方越小
最后,我认为这种方法在行为上与前缀树方法非常相似。在那里,您将构建树,然后迭代树叶(即最大的超集),并将它们祖先的所有项目合并到它们的集合中。ppl在此继续,因此通常希望在帮助之前看到一些努力。你尝试了什么?如果你有一个O(n²)版本,也许你应该发布它作为一个开始。有人可能会找到改进的方法。谢谢你的反馈。下面是一个我想改进的工作示例:这真的是关于流的,还是您正在寻找一种比O(n²)更快的方法?因为仅仅使用流并不能加快速度。但是,如果密钥被认为是相等的(如果它们是彼此的前缀),那么您可以通过使用而不是比较每对密钥来提高速度。那么,
getMatchingKey
做什么呢?@tobias_k你是对的-这不是一个流问题,我只是假设使用流可以更快地完成。我知道前缀树,但这里不是这样,因为我简化了实际问题,并将其简化为比实际问题更容易解释的问题。将编辑问题以包含整个问题,可能是我最初的想法让我走错了方向。。。
for (int i = 0; i < sortedEntries.size() - 1; i++)
{
Entry<Subnet, Set<String>> subnet = sortedEntries.get(i);
Entry<Subnet, Set<String>> potentialSupernet = sortedEntries.get(i + 1);
if (subnet.getKey().isPrefix(potentialSupernet.getKey()))
{
potentialSupernet.getValue().addAll(subnet.getValue());
sortedEntries.remove(i);
i--;
}
}
for (int i = 0; i < sortedEntries.size(); i++)
{
Entry<Subnet, Set<String>> subnet = sortedEntries.get(i);
for (int j = i + 1; j < sortedEntries.size(); j++)
{
Entry<Subnet, Set<String>> nextNet = sortedEntries.get(j);
if (!subnet.getKey().isPrefix(nextNet.getKey()))
{
break;
}
Entry<Subnet, Set<String>> nextNextNet = j < sortedEntries.size() - 1 ? sortedEntries.get(j + 1) : null;
if (nextNextNet == null || !subnet.getKey().isPrefix(nextNextNet.getKey()))
{
// biggest, and last superset found
nextNet.getValue().addAll(subnet.getValue());
sortedEntries.remove(i);
i--;
}
else if (!nextNet.getKey().isPrefix(nextNextNet.getKey()))
{
// biggest superset found, but not last
nextNet.getValue().addAll(subnet.getValue());
}
}
}