我正在努力实现Dijkstra,也在学习Streams.我不能使用流实现下面的代码片段.我正在try 使用STREAMS迭代映射、根据 node 筛选键并更新dist数组,所有这些都在一行中完成.

input adj=[[2,1,1],[2,3,1],[3,4,1]] 
n=4
S(Source)=2


class Pair{
    int node;
    int weight;
    public Pair(int weight,int node) {
        this.node=node;
        this.weight=weight;
    }
}
    
class Solution {
    public int dijkstra(int[][] adj, int n, int S) {
    
        int [] dist=new int[n];
        Arrays.fill(dist,(int)1e9);
        Map <Integer,List<Pair>>  dic;
        dic=new HashMap<>();
       
        for(int i=0;i<adj.length;i++) {
               
            int nd=(int)adj[i][1];
            int wt=(int)adj[i][2];
            Pair p=new Pair(wt,nd);
    
            dic.computeIfAbsent((int)adj[i][0],y->new LinkedList<Pair>()).add(p);
        }
            
        PriorityQueue <Pair>pq=new PriorityQueue<>((x,y)->x.weight-y.weight);
        dist[k-1]=0;
        pq.add(new Pair(0,S));
    
        while(pq.size() > 0) {
    
            int dis=pq.peek().weight;
            int node=pq.peek().node;
            pq.remove();
    
    // How to implement the below code using Streams in one line
    ------------------------------------------------
    
            dic.entrySet().stream()
                .filter(e->e.getKey().equals(node))
                .filter(entry -> entry.getValue()
                .forEach(p->{
                    if(dis+p.weight<dist[p.node-1]){
                    dist[p.node-1]=dis+p.weight;
                    pq.add(new Pair(dis+p.weight,p.node));
                        }
                }));
            }   
        }
    }

```

推荐答案

您的现有代码片段正在try 使用Java的Stream API来迭代映射并应用一系列操作.然而,您开始使用STREAMS的方式并不完全符合STREAMS的预期使用方式.

Java Streams不是为改变外部状态(就像您的dist数组)或执行有副作用的操作而设计的,比如将元素添加到PriorityQueue.流最适合用于纯功能操作,如过滤、映射或收集结果.

也就是说,如果您仍然希望在流的预期使用范围内使用流,则可以通过重构Dijkstra实现中可以在函数上表示的部分来实现.因为您当前的代码不只是过滤(它还更新dist数组并向pq添加元素),所以不可能在不违反这些原则的情况下在单个流操作中完成这项工作.

过滤和处理邻居的流操作可能看起来像这样:

dic.getOrDefault(node, Collections.emptyList()).stream()
        .filter(p -> dis + p.weight < dist[p.node - 1])
        .forEach(p -> {
            dist[p.node - 1] = dis + p.weight;
            pq.add(new Pair(dis + p.weight, p.node));
        });

在上面的代码片段中,filter操作确保我们只处理那些可能更新dist数组的对.然后使用forEach来应用更新.这假设当您从映射中获得配对列表时,您已经在处理当前 node 的邻居,因此您不需要额外的按键过滤.

请注意,由于副作用的原因,这仍然不是完美的"功能性",但在此上下文中仍然使用流的情况下,这是我们所能达到的最接近的效果.

此外,您当前的代码似乎有问题.使用了变量k,但未定义.我假设它应该是S,即源 node ,如果dist[]中的 node 是0索引的,则应该减1,这似乎就是这种情况.

以下是经过更正和重构的代码片段:

class Solution {
    public int dijkstra(int[][] adj, int n, int S) {

        int[] dist = new int[n];
        Arrays.fill(dist, (int)1e9);
        Map<Integer, List<Pair>> dic = new HashMap<>();
   
        for (int[] edge : adj) {
            int src = edge[0];
            int dest = edge[1];
            int weight = edge[2];
            Pair p = new Pair(weight, dest);
            dic.computeIfAbsent(src, k -> new LinkedList<>()).add(p);
        }
        
        PriorityQueue<Pair> pq = new PriorityQueue<>((x, y) -> x.weight - y.weight);
        dist[S - 1] = 0;
        pq.add(new Pair(0, S));

        while (!pq.isEmpty()) {
            Pair current = pq.poll();
            int dis = current.weight;
            int node = current.node;
    
            dic.getOrDefault(node, Collections.emptyList()).stream()
                .filter(p -> dis + p.weight < dist[p.node - 1])
                .forEach(p -> {
                    dist[p.node - 1] = dis + p.weight;
                    pq.add(new Pair(dis + p.weight, p.node));
                });
        }
        
        // Rest of your method, presumably returning the minimum distances or similar
        // For example:
        return dist; // This should be an array of distances from the source node S
    }
}

class Pair {
    int node;
    int weight;

    public Pair(int weight, int node) {
        this.node = node;
        this.weight = weight;
    }
}

确保根据您试图实现的目标从dijkstra方法返回适当的结果,因为如果没有清晰的输出,上面的代码片段是不完整的.

Java相关问答推荐

当耗时的代码完成时,Circular ProgressIndicator显示得太晚

将Nimbus设置为计算机上运行的所有Java应用程序的默认外观

为什么接口中的主函数而不是类中的主函数在Java 17中编译和运行没有问题?

Intellij显示项目语言级别最高为12,尽管有java版本17 SDK

Spark上下文在向Spark提交数据集时具有内容,但Spark在实际构建它时发现它为空

内存中的H2修剪尾随空格

安装Java Jar应用程序的Install4j遇到ClassNotFoundException的运行时错误

从Spring5迁移到Spring6:无法在雅加达包中找到类

如何只修改父类ChroniclerView位置0处的第一个嵌套ChroniclerView(child)元素?

如何仅使用键/ID的一部分(组合)高效地返回映射值?

在Java 15应用程序中运行Java脚本和Python代码

有谁能帮我修一下这个吗?使输出变得更加整洁

如果第一位数字和最后一位数字相差超过一位,您将如何获得随机数?

每次我需要时创建和关闭数据库连接会有什么效果吗?

如何在Maven Central上部署?

我们可以在方法中声明接口吗?

具有多个分析模式的复杂分隔字符串的正则表达式

让标签占用JavaFX中HBox的所有可用空间

如何使用我的RLE程序解决此问题

Java泛型方法重载