I want to read data from a file and construct a graph from it. I did everything, all vertices are created normally, but when I add them to the graph, their adjacent lists (which are maps, whose key value is adjacent vertex's number, and value is their distance) become empty. Can anyone, please, tell what's the problem with my code?
public class Vertex {
private int number;
private LinkedHashMap<Integer, Integer> adjacent;
public Vertex(int num) {
this.number = num;
this.adjacent = new LinkedHashMap<Integer, Integer>();
}
}
public class Graph {
private ArrayList<Vertex> vertices;
private int verticesSize = 201;
public Graph() {
Vertex initialVertex = new Vertex(0);
this.vertices = new ArrayList<Vertex>();
for(int i = 0; i < verticesSize; i++) {
vertices.add(i, initialVertex);
}
}
}
public class Test {
public static void printGraph(Graph graph) {
for(int i = 0; i < graph.getVerticesSize(); i++)
System.out.println(graph.getVertices().get(i));
}
public static void main(String[] args) throws IOException {
FileInputStream fStream = new FileInputStream("C:/Lusine/Programming/Java/dijkstraData.txt");
// Use DataInputStream to read binary NOT text.
BufferedReader bReader = new BufferedReader(new InputStreamReader(fStream));
Graph graph = new Graph();
String[] maps;
String line;
LinkedHashMap<Integer, Integer> currentMap = new LinkedHashMap<Integer, Integer>();
while( (line = bReader.readLine()) != null) {
maps = line.split("\t");
int firstDigit = Integer.parseInt(maps[0]);
Vertex v = new Vertex(firstDigit);
for(int i = 1; i < maps.length; i++) {
String[] vertexDistance = maps[i].split(",");
int vertex = Integer.parseInt(vertexDistance[0]);
int distance = Integer.parseInt(vertexDistance[1]);
currentMap.put(vertex, distance);
}
v.setAdjacent(currentMap);
graph.getVertices().set(firstDigit, v);
System.out.println("\n" + firstDigit +"-th vertex is\n" + v);
currentMap.clear();
}
printGraph(graph);
}
when I print v, it's ok, but when I print graph, all adjacent lists are empty. What's the problem?
Your loop boils down to
LinkedHashMap<Integer, Integer> currentMap = new LinkedHashMap<Integer, Integer>();
while ( ... ) {
Vertex v = new Vertex(...);
v.setAdjacent(currentMap);
currentMap.clear();
}
So, you're storing the same map of adjacent vertices in every vertex, and you clear this map at the end of each iteration. So obviously, all the vertices share the same, empty map, at the end of the loop.
You should create a new LinkedHashMap at every iteration:
while ( ... ) {
LinkedHashMap<Integer, Integer> currentMap = new LinkedHashMap<Integer, Integer>();
Vertex v = new Vertex(...);
v.setAdjacent(currentMap);
}
And you should not clear it, cince clearing it, well... clears it.
Related
**can someone find the error and send the code please i am new to java
i am unable to find the error
the following are error showing
Note: PrimAlgorithmPQBetter.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details. Error: Main method
not found in class PrimAlgorithmPQBetter, please define the main
method as: public static void main(String[] args) or a JavaFX
application class must extend javafx.application.Application
import javafx.util.Pair;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
public class PrimAlgorithmPQBetter {
static class Edge {
int source;
int destination;
int weight;
public Edge(int source, int destination, int weight) {
this.source = source;
this.destination = destination;
this.weight = weight;
}
}
static class ResultSet {
int parent;
int weight;
}
static class Graph {
int vertices;
LinkedList<Edge>[] adjacencylist;
Graph(int vertices) {
this.vertices = vertices;
adjacencylist = new LinkedList[vertices];
//initialize adjacency lists for all the vertices
for (int i = 0; i <vertices ; i++) {
adjacencylist[i] = new LinkedList<>();
}
}
public void addEgde(int source, int destination, int weight) {
Edge edge = new Edge(source, destination, weight);
adjacencylist[source].addFirst(edge);
edge = new Edge(destination, source, weight);
adjacencylist[destination].addFirst(edge); //for undirected graph
}
public void primMST(){
boolean[] mst = new boolean[vertices];
ResultSet[] resultSet = new ResultSet[vertices];
int [] key = new int[vertices]; //keys used to store the key to know whether priority queue update is required
//Initialize all the keys to infinity and
//initialize resultSet for all the vertices
for (int i = 0; i <vertices ; i++) {
key[i] = Integer.MAX_VALUE;
resultSet[i] = new ResultSet();
}
//Initialize priority queue
//override the comparator to do the sorting based keys
PriorityQueue<Pair<Integer, Integer>> pq = new PriorityQueue<>(vertices, new Comparator<Pair<Integer, Integer>>() {
#Override
public int compare(Pair<Integer, Integer> p1, Pair<Integer, Integer> p2) {
//sort using key values
int key1 = p1.getKey();
int key2 = p2.getKey();
return key1-key2;
}
});
//create the pair for for the first index, 0 key 0 index
key[0] = 0;
Pair<Integer, Integer> p0 = new Pair<>(key[0],0);
//add it to pq
pq.offer(p0);
resultSet[0] = new ResultSet();
resultSet[0].parent = -1;
//while priority queue is not empty
while(!pq.isEmpty()){
//extract the min
Pair<Integer, Integer> extractedPair = pq.poll();
//extracted vertex
int extractedVertex = extractedPair.getValue();
mst[extractedVertex] = true;
//iterate through all the adjacent vertices and update the keys
LinkedList<Edge> list = adjacencylist[extractedVertex];
for (int i = 0; i <list.size() ; i++) {
Edge edge = list.get(i);
//only if edge destination is not present in mst
if(mst[edge.destination]==false) {
int destination = edge.destination;
int newKey = edge.weight;
//check if updated key < existing key, if yes, update if
if(key[destination]>newKey) {
//add it to the priority queue
Pair<Integer, Integer> p = new Pair<>(newKey, destination);
pq.offer(p);
//update the resultSet for destination vertex
resultSet[destination].parent = extractedVertex;
resultSet[destination].weight = newKey;
//update the key[]
key[destination] = newKey;
}
}
}
}
//print mst
printMST(resultSet);
}
public void printMST(ResultSet[] resultSet){
int total_min_weight = 0;
System.out.println("Minimum Spanning Tree: ");
for (int i = 1; i <vertices ; i++) {
System.out.println("Edge: " + i + " - " + resultSet[i].parent +
" key: " + resultSet[i].weight);
total_min_weight += resultSet[i].weight;
}
System.out.println("Total minimum key: " + total_min_weight);
}
public static void main(String[] args) {
int vertices = 6;
Graph graph = new Graph(vertices);
graph.addEgde(0, 1, 4);
graph.addEgde(0, 2, 3);
graph.addEgde(1, 2, 1);
graph.addEgde(1, 3, 2);
graph.addEgde(2, 3, 4);
graph.addEgde(3, 4, 2);
graph.addEgde(4, 5, 6);
graph.primMST();
}
}
}
I'm using Tarjan's Algorithm to find critical connections in an undirected graph. However when the input has 100000 vertices, it sometimes throws an TLE. I searched around and could not find out why.
I tried to implement the iterative version of Tarjan's algo but couldn't figure it out.
Is there any further improvement over the code?
Testcase Link: https://leetcode.com/submissions/detail/276043932/testcase/
import java.util.*;
class SevenSixThree {
// the order of visiting vertices
private int[] ord;
// the lowest index of the vertex that this vertex can reach
private int[] low;
// keep track of the current order;
private int count;
// result
private List<List<Integer>> result;
// graph
private Map<Integer, List<Integer>> graph;
private boolean[] visited;
public static void main(String[] args) {
SevenSixThree s = new SevenSixThree();
List<List<Integer>> list = new ArrayList<>();
List<Integer> l1 = new ArrayList<>();
l1.add(0);
l1.add(1);
list.add(new ArrayList<>(l1));
List<Integer> l2 = new ArrayList<>();
l2.add(0);
l2.add(2);
list.add(new ArrayList<>(l2));
List<Integer> l3 = new ArrayList<>();
l3.add(1);
l3.add(2);
list.add(new ArrayList<>(l3));
List<Integer> l4 = new ArrayList<>();
l4.add(1);
l4.add(3);
list.add(new ArrayList<>(l4));
List<List<Integer>> res = s.criticalConnections(4, list);
System.out.print(res.toArray().toString());
}
public List<List<Integer>> criticalConnections(int n, List<List<Integer>> connections) {
// find bridge of a graph.
// first, build the graph with map
HashMap<Integer, List<Integer>> graph = new HashMap<>();
for (int i = 0; i < n; i++) {
graph.put(i, new ArrayList<>());
}
for (List<Integer> connection : connections) {
int v = connection.get(0);
int w = connection.get(1);
graph.get(v).add(w);
graph.get(w).add(v);
}
ord = new int[n];
low = new int[n];
visited = new boolean[n];
Arrays.fill(visited, false);
result = new ArrayList<>();
dfs(0, -1, graph);
return result;
}
private void dfs(int v, int parent, HashMap<Integer, List<Integer>> graph) {
// visit this vertex
visited[v] = true;
ord[v] = count++;
low[v] = ord[v];
List<Integer> adjs = graph.get(v);
for (int w : adjs) {
if (!visited[w]) {
dfs(w, v, graph);
low[v] = Math.min(low[w], low[v]);
if (low[w] > ord[v]) {
List<Integer> bridge = new ArrayList<>();
bridge.add(v);
bridge.add(w);
result.add(bridge);
}
} else {
if (w != parent) {
low[v] = Math.min(low[v], low[w]);
}
}
}
}
I have implemented a directed graph in java, using Map data structure.
Currently, I have two Map data structures:
Holds each Node, with All in-degree vertices.
Holds each Node, with All out-degree vertices.
My problem is as follows:
I would like to implement a shortest path algorithm that, given a specific node and a secondary node, finds the shortest path between the first node to the second node.
I am not sure how to implement it using Map data structure.
public class NetworkInfluence {
private int numEdges; //number of edges
private int numVert; //number of vertices
private int numIter; //number of page rank iterations
private Map<String, List<String>> AtoB; //out degree of vertices
private Map<String, List<String>> BtoA; //in degree of vertices
private Map<String, Double> influenceMap; //page ranks of vertices
private Set<String> nodeCounter; //list of vertices
/**
* Creates a new PageRank object. This is used to find the pagerank
* of a graph represented as an edgelist in a text file.
* #param fileName Name of text file containing graph edge list.
* #param eps Convergence parameter for pagerank.
* #throws FileNotFoundException If text file containing graph cannot be found.
* #throws IOException If error reading a text file.
*/
public NetworkInfluence(String fileName) throws FileNotFoundException, IOException {
numIter = 0;
numEdges = 0;
AtoB = new HashMap<String, List<String>>();
BtoA = new HashMap<String, List<String>>();
Set<String> nodeCounter = new HashSet<String>();
FileReader fr = new FileReader(fileName);
BufferedReader b = new BufferedReader(fr);
String line = b.readLine();
String nodes[];
List<String> toList;
List<String> fromList;
while((line = b.readLine()) != null) {
numEdges++;
nodes = line.toLowerCase().split(" ");
//A->B
if(!AtoB.containsKey(nodes[0])) {
toList = new ArrayList<String>();
toList.add(nodes[1]);
AtoB.put(nodes[0], toList);
} else {
toList = AtoB.get(nodes[0]);
toList.add(nodes[1]);
AtoB.put(nodes[0], toList);
}
//B->A
if(!BtoA.containsKey(nodes[1])) {
fromList = new ArrayList<String>();
fromList.add(nodes[0]);
BtoA.put(nodes[1], fromList);
} else {
fromList = BtoA.get(nodes[1]);
fromList.add(nodes[0]);
BtoA.put(nodes[1], fromList);
}
nodeCounter.add(nodes[0]);
nodeCounter.add(nodes[1]);
}
this.nodeCounter = nodeCounter;
numVert = nodeCounter.size();
b.close();
Any help would be appreciated. Thanks.
As mentioned you can solve it with dijkstra even if you are using hashmaps. In addition to your structure you have to somehow the costs of edges, something like this:
Map<String, Map<String, Integer>> costs = new HashMap<>();
...
// where the cost of edge ("node0", "node1") is:
int cost = costs.get("node0").get("node1");
the part od dijkstra may be something like this (i did not care about optimizing map access):
public List<String> path(String node0, String node1) {
// array to keep trace of visited nodes
Map<String, Boolean> visited = new HashMap<>();
// array to keep trace of predecessors of nodes in the path
Map<String, String> pred = new HashMap<>();
// initialize maps
for (String n : nodeCounter) {
visited.put(n, false);
pred.put(n, node0);
}
// min costs from node0 to any other node, initialized to INFINITE if
// the nodes are not adjacent
Map<String, Integer> mincosts = new HashMap<>();
for (String n : nodeCounter)
mincosts.put(n, costs.get(node0).get(n));
// initialize flags of start node
visited.put(node0, true);
mincosts.put(node0, 0);
// iterate until all vertexes or node1 are reached
for (int i = 0; (i < numVert) && (!visited.get(node1)); ++i) {
int min = inf;
String candidate = null;
for (String n : nodeCounter)
if (!visited.get(n) && mincosts.get(n) < min) {
min = mincosts.get(n);
candidate = n;
}
if (candidate == null)
break;
visited.put(candidate, true);
for (String n : nodeCounter)
if (!visited.get(n) && ((mincosts.get(candidate) + costs.get(candidate).get(n)) < mincosts.get(n))) {
mincosts.put(n, mincosts.get(candidate) + costs.get(candidate).get(n));
pred.put(n, candidate);
}
}
if (!visited.get(node1))
return null;
// store the path from node1 to node0, using predecessors
// map
String current = node1;
List<String> path = new ArrayList<>();
path.add(current);
while (!current.equals(node0))
path.add(current = pred.get(current));
// store the path from node0 to node1
Collections.reverse(path);
return path;
}
Actually, if you can use also third libraries, i suggest you to look for a graph java library like JGraphT, and use the given functions for minimum paths. For example here is the reference for the Dijkstra JGraphT API.
I am working on a problem I came across in an interview.
Input contains Population|City|State|Interstates list
Output needs to be sorted in descending order by population first, then alphabetically by city and state, and then the interstates need to be sorted in ascending order too.
Sample input:
27|Chicago|Illinois|I-94;I-90;I-88;I-57;I-55
83|New York|New York|I-78;I-95;I-87;I-80
15|Phoenix|Arizona|I-10;I-17;I-8
15|Philadelphia|Pennsylvania|I-95;I-76
Sample output:
83
New York, New York
Interstates: I-78, I-80, I-87, I-95
27
Chicago, Illinois
Interstates: I-55, I-57, I-88, I-90, I-94
15
Philadelphia, Pennsylvania
Interstates: I-76, I-95
Phoenix, Arizona
Interstates: I-8, I-10, I-17
Here's my approach so far. I am currently stuck in the if block where I've added a comment. I am not sure if I am going in the right direction. I am looking for a hint to take the right approach here.
Scanner sc = new Scanner(System.in);
String line;
List<String> al = new ArrayList<>();
//Outer map sorts reverse by population, inner map1 sorts by city, inner
map2 sorts by state
Map<Integer, Map<String, Map<String, String>>> outerMap = new TreeMap<>
(Collections.reverseOrder());
Map<String, Map<String, String>> innerMap1 = new TreeMap<>();
Map<String, String> innerMap2 = new TreeMap<>();
while(sc.hasNextLine() && (line = sc.nextLine()).length()!=0) {
//Ignore if input contains this character
if(line.contains("#")) {
line = sc.nextLine();
}
al.add(line);
}
for(int i = 0; i < al.size(); i++) {
int outerMapKey = Integer.parseInt(al.get(i).split("\\|")[0]);
String innerMap1Key = al.get(i).split("\\|")[1];
String innerMap2Key = al.get(i).split("\\|")[2];
String value = al.get(i);
outerMap.get(outerMapKey);
if(outerMap.containsKey(outerMapKey)) {
innerMap1 = outerMap.get(outerMapKey);
/* Logic to put values in inner maps
This is going to get very convoluted, not sure if I have the
right approach
*/
}
else {
innerMap1 = new TreeMap<>();
innerMap2 = new TreeMap<>();
innerMap2.put(innerMap2Key, value);
innerMap1.put(innerMap1Key, innerMap2);
outerMap.put(outerMapKey, innerMap1);
}
}
Thank you for all your help so far. I am posting my code (working now) based on feedback here. Please take a look and suggest how it can be improved.
public static void main(String[] args) {
Map<String, List<PopulationByCityState>> map = readAndProcessInput();
printSortedOutput(map);
}
private static Map<String, List<PopulationByCityState>> readAndProcessInput() {
Map<String, List<PopulationByCityState>> map = readInput();
sortByPopulationCityAndState(map);
return map;
}
private static Map<String, List<PopulationByCityState>> readInput() {
System.out.println("Enter input:");
Scanner sc = new Scanner(System.in);
String line;
Map<String, List<PopulationByCityState>> map = new TreeMap<>(Collections.reverseOrder());
while (sc.hasNextLine() && (line = sc.nextLine()).length() != 0) {
if (line.contains("#")) {
line = sc.nextLine();
}
populateMap(line, map);
}
return map;
}
private static void populateMap(String line, Map<String, List<PopulationByCityState>> map) {
String[] s = line.split("\\|");
String[] is = s[3].split(";");
String key = s[0];
PopulationByCityState p = new PopulationByCityState();
p.setPopulation(Long.parseLong(s[0]));
p.setCity(s[1]);
p.setState(s[2]);
List<String> interstates = new ArrayList<>();
for (String aString : is) {
interstates.add(aString);
}
sortInterstates(interstates);
p.setInterstates(interstates);
if (map.containsKey(key)) {
map.get(key).add(p);
} else {
List<PopulationByCityState> al = new ArrayList<>();
al.add(p);
map.put(key, al);
}
}
private static void sortInterstates(List<String> interstates) {
Collections.sort(interstates, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
int n1 = Integer.parseInt(o1.split("-")[1]);
int n2 = Integer.parseInt(o2.split("-")[1]);
return n1 - n2;
}
});
}
private static void sortByPopulationCityAndState(Map<String, List<PopulationByCityState>> map) {
for (Map.Entry entry : map.entrySet()) {
List<PopulationByCityState> list = (List<PopulationByCityState>) entry.getValue();
Collections.sort(list, new Comparator<PopulationByCityState>() {
#Override
public int compare(PopulationByCityState o1, PopulationByCityState o2) {
int c;
c = (int) (o2.getPopulation() - o1.getPopulation());
if (c == 0) {
c = o1.getCity().compareTo(o2.getCity());
}
if (c == 0) {
c = o1.getState().compareTo(o2.getState());
}
return c;
}
});
}
}
private static void printSortedOutput(Map<String, List<PopulationByCityState>> map) {
for (Map.Entry<String, List<PopulationByCityState>> entry : map.entrySet()) {
System.out.println(entry.getKey());
System.out.println();
List<PopulationByCityState> list = entry.getValue();
for (PopulationByCityState p : list) {
System.out.println(p.getCity() + ", " + p.getState());
List<String> interstates = p.getInterstates();
System.out.print("Interstates: ");
int s = 0;
for (String is : interstates) {
s++;
System.out.print(is);
if (s != interstates.size()) {
System.out.print(", ");
}
}
System.out.println();
System.out.println();
}
}
}
Your approach relies on over complicated and not meaningful structure and also uses a Comparator that will only sort the first level of the map :
Map<Integer, Map<String, Map<String, String>>> outerMap = new TreeMap<>
(Collections.reverseOrder());
A finer approach could rely on using a class that represents each individual information that you need to represent a population for a state : PopulationForState
Here is a very simple representation of it (that is of course improvable but that should help you to understand the logic) :
public class PopulationForState{
private long population;
private String city;
private String state;
private List<String> interstates;
...
// getters
}
Add instances of them in a List and use a comparator that sorted them in descending order by population first, then alphabetically by city and state.
The interstates field may be sorted independently or directly during the sort of outer elements.
You could provide a sort method in PopulationForState, for example sortInnerStates() that sorts them in ascending order.
Personally, I would make it independently to keep the processing less coupled between.
So you could write something like :
List<PopulationForState> populationForStates = new ArrayList<>();
populationForStates.add(new PopulationForState(...));
populationForStates.add(new PopulationForState(...));
Collection.sort(populationForStates, Comparator.comparing(PopulationForState::population).reversed()
.thenComparing(PopulationForState::getCity)
.thenComparing(PopulationForState::getState);
populationForStates.stream()
.forEach(PopulationForState::sortInnerStates);
If you have a structure such the one posted in above post:
public class PopulationForState{
public long population;
public String city;
public String state;
public List<String> interstates;
//Do encapsulate
}
You can sort it with one comparator:
Collections.sort(populatisForStates, new Comparator<PopulationForState>(){
public int compare(PopulationForState first, PopulationForState scnd) {
int compare = first.population - scnd.population;
if(compare != 0) return compare;
compare = first.city.compareTo(scnd.city);
if(compare != 0) return compare;
return first.state.compareTo(scnd.state);
}
});
Sorting Interstates is similar and you just need to use Collections.sort(interstates) on each instance.
Can anyone help me figure it out how to solve my problem. I need to find the shortest path between 2 given nodes. So far I have managed to save all posible paths in a list, and now I'm trying to find the minimal distance.
here is my code:
public class A {
private static int[][] adjacency = new int [6][6];
static int n = 6;
private static final int START = 1;
private static final int END = 4;
private Map<Integer, LinkedHashSet<Integer>> map = new HashMap();
private Map<Integer, List<Integer>> pathsFound = new HashMap();
public void addEdge(int node1, int node2) {
LinkedHashSet<Integer> adjacent = map.get(node1);
if(adjacent==null) {
adjacent = new LinkedHashSet();
map.put(node1, adjacent);
}
adjacent.add(node2);
}
public LinkedList<Integer> adjacentNodes(Integer last) {
LinkedHashSet<Integer> adjacent = map.get(last);
if(adjacent==null) {
return new LinkedList();
}
return new LinkedList<Integer>(adjacent);
}
public static void main(String[] args) {
LinkedList<Integer> visited = new LinkedList<Integer>();
visited.add(START);
A graph = new A();
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
adjacency[i][j] = 0;
adjacency[0][1] = 1;
adjacency[0][2] = 2;
adjacency[1][0] = 1;
adjacency[1][3] = 5;
adjacency[1][4] = 9;
adjacency[1][5] = 6;
adjacency[2][0] = 2;
adjacency[2][4] = 7;
adjacency[2][5] = 2;
adjacency[3][1] = 5;
adjacency[4][1] = 9;
adjacency[4][2] = 7;
adjacency[4][5] = 1;
adjacency[5][1] = 6;
adjacency[5][2] = 2;
adjacency[5][4] = 1;
graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(1,0);
graph.addEdge(1,3);
graph.addEdge(1,4);
graph.addEdge(1,5);
graph.addEdge(2,0);
graph.addEdge(2,4);
graph.addEdge(2,5);
graph.addEdge(3,1);
graph.addEdge(4,1);
graph.addEdge(4,2);
graph.addEdge(4,5);
graph.addEdge(5,1);
graph.addEdge(5,2);
graph.addEdge(5,4);
graph.breadthFirst(visited);
}
public void breadthFirst(LinkedList<Integer> visited) {
LinkedList<Integer> nodes = adjacentNodes(visited.getLast());
List<List<Integer>> allPaths = new ArrayList<List<Integer>>();
List<Integer> distances = new ArrayList<Integer>();
for (int node : nodes) {
if (visited.contains(node))
continue;
if (node == END) {
visited.add(node);
List<Integer> path = getPath(visited);
System.out.println(path);
??allPaths.add(path);
visited.removeLast();
break;
}
}
for (int node : nodes) {
if (visited.contains(node) || node == END)
continue;
visited.addLast(node);
breadthFirst(visited);
visited.removeLast();
}
System.out.println(allPaths.get(0));
}
public static List<Integer> getPath(LinkedList<Integer> visited) {
List<Integer> path = new ArrayList<Integer>();
for (int node : visited)
path.add(node);
return path;
}
}
If I do like this System.out.println(path); it prints the path, which means that the function getPath() works.
But when I want to put this path in a list : allPaths.add(path); something goes wrong, because when I call after the for loop end System.out.println(allPaths.get(0)); I get an IndexOutOfBoundException. I really don't understand why my allPaths list is empty...
Why don't you iterate with a foreach ?
for (int number : arrlist) {
System.out.println("Number = " + number);
}
Are you perhaps invoking the last snippet (in your question) before you have filled in the distances collection? You need to invoke it afterwards, not before.
[Aside: In the future, if you have an exception, you really need to provide the exception message and stack trace. Makes helping you much easier...]