Java流:按函数合并映射键

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

我有一张地图。如果一个键是另一个键的函数,我希望合并键,例如:

如果函数为“prefix”,我希望在映射中给出以下值:

{"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());
        }
    }
}