如何修复在另一个类中被修改的私人列表

时间:2019-04-09 19:28:38

标签: java

对于一个学校项目,他们要求我们制作dijkstra的算法。 我有以下课程:Node,Edge,graph和Dijkstra 使用graph.getNodes(返回列表)并将其存储在findPath的局部变量中(在djikstra中) 使用查找路径graph.getnodes后返回大小为5的列表,而不是来自graph.java的getNodes findPath来自Djikstra.java

public List<Node> getNodes() {
    return nodes;
}

public void findPath (Node s, Node d) {
        System.out.println("nodeSize at begining of findpath : "+graph.getNodes().size());
        List<Node> nodes = graph.getNodes();
        dijkstraTable = new Map[nodes.size()];
        //verify paramaters
        if(!nodes.contains(s)) throw new InvalidParameterException("the source node is not valid");
        if(!nodes.contains(d)) throw new InvalidParameterException("the destination node is not valid");
        if(s == null || d == null ) throw new NullPointerException("s or d are null");
        Edge edge0 = new Edge(s,s,0);
        Map<Node,Edge> map = new HashMap<Node,Edge>();
        map.put(s, edge0);
        int i =0;
        dijkstraTable[i] = map;
        //iteration > 0 
        while(!nodes.isEmpty()) {
            i++;
            if (i==nodes.size()) break;
            Map<Node,Edge> newMap = new HashMap<Node,Edge>();
            map = dijkstraTable[i-1]; //last iteration map 
            //get minimum last iteration
            Node min = getMinimum(map);
            //mark it as "visited" 
            nodes.remove(min);
            //add it to the path
            List<Edge> edges = graph.getEdgesGoingFrom(min);
            System.out.println("nodeSize in loop: "+graph.getNodes().size());
            for(Edge edge : edges) {
                Node key = edge.getDestination();
                if(!map.containsKey(key)) { //create it if doesnt exist
                    newMap.put(key, edge);
                }else { //make sure to have the minimum value
                    if(getMinimum(map.get(key), edge) == edge) newMap.put(key, edge);
                    else newMap.put(key, map.get(key));
                }
            }//endfor
            path.add(map.get(min));
            dijkstraTable[i] = newMap;
        }
        System.out.println("nodeSize at end of findpath : "+graph.getNodes().size());
    }

输出为

findpath开头的

nodeSize:7

nodeSize循环:6

nodeSize循环:5

nodeSize循环:5

nodeSize循环:5

nodeSize位于findpath的末尾:5

应该每次7点

2 个答案:

答案 0 :(得分:1)

您的问题在这里:

import pandas as pd
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, HoverTool
from bokeh.transform import linear_cmap
from bokeh.palettes import Spectral6, RdYlGn, viridis, Plasma256, RdYlGn10, YlOrRd4, Reds9
from bokeh.tile_providers import CARTODBPOSITRON_RETINA
from pygeotile.point import Point
from bokeh.embed import components
from bokeh.resources import INLINE
from django.shortcuts import render_to_response

#output_notebook()
#%matplotlib inline

pred = r'path'
pred = pd.read_csv(pred)

for index, row in pred.iterrows():
        point = Point.from_latitude_longitude(latitude=row['Latitude'], longitude=row['Longitude'])
        pred.at[index,'x'] = point.meters[0]
        pred.at[index,'y'] = point.meters[1]
        pred.at[index,'size'] = 15 # int(row[bnf]/100)

p = figure(plot_width=900, plot_height=400, 
           x_axis_type="mercator", 
           y_axis_type="mercator",
           x_range=(-928267, -573633), 
           y_range=(7168390, 7422161))
p.add_tile(CARTODBPOSITRON_RETINA)

mapper = linear_cmap(field_name='type', palette=Spectral6,low=0 ,high=1)

source = ColumnDataSource(pred_crime)
p.circle(x='x', y='y', source=source, size='size', fill_color=mapper, line_alpha=0.5, line_color='black')
p.add_tools(HoverTool(tooltips=[("type","Type")]))
script, div = components(p)
return render_to_response('index.html', {'resources' = INLINE.render(), 'script': script, 'div': div})

您正在使用方法public List<Node> getNodes() { return nodes; } ... List<Node> nodes = graph.getNodes(); 修改“私人”列表。如果要避免修改,请使用findPath int Collections.unmodifiableList(nodes)或在getNodes()中创建一个新列表,并将findPath传递给列表构造函数。

答案 1 :(得分:1)

更改

List<Node> nodes = graph.getNodes();

List<Node> nodes = new ArrayList<>(graph.getNodes());

这将在findPath方法中创建列表的本地副本。

或者您可以更改

public List<Node> getNodes() {
    return nodes;
}

public List<Node> getNodes() {
    return new ArrayList<>(nodes);
}

这将在getNodes()方法中返回列表的副本。