I know this has been asked a lot in stackoverflow but I could not find answers that work to my problem.
In the following code below, I cant print out each item in ArrayList<Integer> because it says that "Edge cannot be cast to java.lang.Integer".
I have tried to print each item using for(Integer item :p1) and also for (int item: p1) but both did not work.
I think maybe the problem is because of the toString() method in Edge class but if i do not use toString() I cant get the real key number (it will be printed as Edge#28a418fc or something like this)
Thanks for helping before
Main class
public class Ranker7 {
static Graph g;
static Node n;
static Edge e;
static HashMap<Integer, Node> nodeMap;
int id;
static double weight;
static int year;
static int type;
Ranker7() {
g = new Graph();
nodeMap = new HashMap<Integer, Node>();
n = new Node(id,year,type,weight);
}
public static void main (String[] args) throws Exception{
long startTime = System.currentTimeMillis();
/**Rule Mining**/
Ranker7 Ranker = new Ranker7();
Connection connect = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
PreparedStatement preparedStatement2 = null;
ResultSet resultSet2 = null;
HashMap nodeMap = new HashMap();
System.out.println("Processing...");
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager.getConnection("jdbc:mysql://localhost/arnetminer?"+"user=root&password=1234");
preparedStatement = connect.prepareStatement("Select fr,t,ty from subedge");
resultSet = preparedStatement.executeQuery();
int i=0;
while(resultSet.next()) {
g.addEdgeForIndexing(resultSet.getInt(1),resultSet.getInt(2),resultSet.getInt(3));
i++;
System.out.println( "edges added to G = "+i);
}
System.out.println("Loaded " + g.nodeCount() + " nodes.");
preparedStatement = connect.prepareStatement("Select node,year,type from subnode2");
resultSet = preparedStatement.executeQuery();
int h=0;
while(resultSet.next()) {
Node n = new Node(resultSet.getInt(1), resultSet.getInt(2),resultSet.getInt(3),weight);
int key1=resultSet.getInt(1);
nodeMap.put(key1,n);
h++;
}
System.out.println(nodeMap);
System.out.println(nodeMap.size());
Scanner sc = new Scanner(System.in);
System.out.println("How many authors do you want to enter?");
int num = sc.nextInt();
int[] authorNames = new int[num];
for(int a = 0; a < authorNames.length; a++){
System.out.println("Enter author name:");
authorNames[a] = sc.nextInt();
}
System.out.println("Year : ");
int inputYear3 = sc.nextInt();
ArrayList<Integer> p1 = new ArrayList<Integer>();
/**Get the papers written by input author A-P**/
for(int b=0; b< authorNames.length;b++){
int AuthorID1 = authorNames[b];
p1 = g.getOutEdgesToP(AuthorID1);
}
for(int item : p1){ //the error of classcastexception is here
System.out.println(item);
}
}
}
Edge class
public class Edge {
int from;
int to;
int type;
private static int counter = 0;
public Edge(int from, int to, int type) {
this.from = from;
this.to = to;
this.type = type;
// System.out.println("edges added from " + from + " to " + to + " with type "+ type);
}
public String toString(){
String repr = Integer.toString(to);
return repr;
}
public int getfrom(){
return from;
}
public int getto(){
return to;
}
public int getType(){
return type;
}
public void setfrom(int from){
this.from = from;
}
public void setto(int to){
this.to = to;
}
public void setType(int type){
this.type = type;
}
}
Graph class
import java.lang.reflect.Field;
import java.util.*;
public class Graph {
private HashSet<Integer> nodeIDs;
public HashMap<Integer, String> nodeIDsWithTN;
public HashMap<Integer, String> TNMap;
private HashMap<Integer, ArrayList<Integer>> edges;
private HashMap<Integer, ArrayList<Integer>> reverse;
private int numNodes;
private int numEdges;
private int numReverse;
public Graph() {
edges = new HashMap<Integer, ArrayList<Integer>>();
reverse = new HashMap<Integer, ArrayList<Integer>>();
nodeIDs = new HashSet<Integer>();
nodeIDsWithTN = new HashMap<Integer, String>();
TNMap = new HashMap<Integer, String>();
new HashSet();
}
public void addEdgeForIndexing(int from, int to, int T) throws IllegalArgumentException, IllegalAccessException {
Edge e = new Edge(from,to,T);
nodeIDs.add(e.from);
nodeIDs.add(e.to);
ArrayList tmp = null;
if (edges.containsKey(e.from))
tmp = (ArrayList) edges.get(e.from);
else {
tmp = new ArrayList();
edges.put(e.from,tmp);
}
tmp.add(e);
ArrayList tmp2 = null;
if (reverse.containsKey(e.to))
tmp2 = (ArrayList) reverse.get(e.to);
else {
tmp2 = new ArrayList();
reverse.put(e.to,tmp2);
}
tmp2.add(e);
}
public int nodeCount() {
if(nodeIDs.size() > 0)
return nodeIDs.size();
// else return numNodes;
return numEdges;
}
public int countInEdges(Integer key) {
if (!reverse.containsKey(key)) return 0;
return ((ArrayList<?>) reverse.get(key)).size();
}
public int countOutEdges(Integer key) {
if (!edges.containsKey(key)) return 0;
return ((ArrayList<?>) edges.get(key)).size();
}
/**
public ArrayList<String> getInEdgesFromPtoA(String id) {
if (!reverse.containsKey(id)) return null;
ArrayList<String> a = reverse.get(id);
ArrayList<String> result = new ArrayList<String>();
for(int j=0;j<a.size();j++){
if(a.get(j).startsWith("A")){
result.add(a.get(j));
}
}
return result;
}
**/
public ArrayList<Integer> getOutEdges(Integer key) {
if (!edges.containsKey(key))
return null;
ArrayList<Integer> value = edges.get(key);
return value;
}
public ArrayList<Integer> getOutEdgesToP(int id) {
if (!edges.containsKey(id)) {
return null;
}
ArrayList<Integer> a = edges.get(id);
System.out.println ("Arraylist a: " + a); //if i print using this its okay. but i cant get each item in this ArrayList like below
for(int item : a){ //the error of classcastexception is here
System.out.println(item);
}
return a;
}
public Iterator<Integer> nodeIteratorInitial() {
return nodeIDs.iterator();
}
}
Node class
public class Node {
int id;
double weight;
int year;
int type;
private static int counter = 0;
public Node(int id,int year,int type,double weight) {
this.id = id;
this.year=year;
this.weight = weight;
this.type = type;
}
#Override
public String toString() {
// here you can create your own representation of the object
String repr = "id:" + id + ", year:" + year + ", weight:" + weight + ", node type:" + type;
return repr;
}
public double getWeight(){
return weight;
}
public int getid() {
return id;
}
public int getType() {
return type;
}
public int getYear() {
return year;
}
public void setWeight(double weight){
this.weight=weight;
}
public void setid(int id){
this.id=id;
}
public void setType() {
this.type=type;
}
}
private HashMap<Integer, ArrayList<Integer>> edges;
// ...later
Edge e = new Edge(from,to,T);
// ...later
else {
tmp = new ArrayList();
edges.put(e.from,tmp);
}
tmp.add(e);
Ultimately, this is a classic example of why raw types are bad. You've got an ArrayList<Integer> and you put Edges in it.
Unfortunately, I don't know how to tell you how to fix it since I don't understand what you're trying to do.
the error lies here
public void addEdgeForIndexing(int from, int to, int T) throws IllegalArgumentException, IllegalAccessException {
Edge e = new Edge(from,to,T);
nodeIDs.add(e.from);
nodeIDs.add(e.to);
ArrayList tmp = null;
if (edges.containsKey(e.from))
tmp = (ArrayList) edges.get(e.from);
else {
tmp = new ArrayList();
edges.put(e.from,tmp);
}
tmp.add(e);//adding an edge to tmp
later in the code you get the ArrayList out of the Map as ArrayList but it an ArrayList containing Edge
try to change
tmp = new ArrayList();
to
tmp = new ArrayList<Integer>();
you should get a compilation error when adding an Edge to it
You declare:
int from;
int to;
int type;
and you should declare them as Integers instead:
Integer from;
Integer to;
Integer type;
because later on you're doing:
this.from = new Integer(from);
etc.
A better option would be to change the assignment to:
this.from = from;
which would also solve this error since you would be assigning an int to an int. Is there a purpose you're using new Integer() ? because if not - I would suggest removing it - it's slower (performance-wise) comparing to the primitive int.
Bottom line: stay consistent and either use int throughout the code, or Integer - try not to mix them unless it's really required.
public ArrayList<Integer> getOutEdgesToP(int id) {
if (!edges.containsKey(id)) {
return null;
}
System.out.println(edges.get(id));
ArrayList<Integer> a = edges.get(id);
System.out.println("Arraylist a: " + a); // if i print using this its
// okay. but i cant get each
// item in this ArrayList like
// below
for (Object item : a) { // the error of classcastexception is here
System.out.println(item);
}
return a;
}
This should work. I don't have a lot of time to search for an explanation.
Related
I have a vertex I am trying to reach, called destination. Currently my algorithm seems to run past this vertex.
It appears that the last edge to get tested for the shortest distance is always added. I'm not sure if this is due to an error in my algorithm or how I add Neighbors, but I have been trying to test both.
Sometimes the last 2 edges get added, ex:
ID: 39330 Value: 1.309999942779541
ID: 39360 Value: 1.940000057220459
ID: 39374 Value: 1.9700000286102295
Added: 39360 Added: 39374
Or just the last one is added:
ID: 39347 Value: 1.2999999523162842
ID: 24955 Value: 2.5799999237060547
Added: 24955
Any thoughts, recommendations or ideas are greatly appreciated!
Graph
class Graph {
private final Set<Vertex> vertices = new HashSet<Vertex>();
private final Set<Edge> edges = new HashSet<Edge>();
public void addVertex(int id, String name) {
Vertex vertex = new Vertex(id,name);
vertices.add(vertex);
//System.out.println("ID:" + vertex.getID() + "Name:" + vertex.getName());
}
public void addEdge(double weight, Vertex vertex1, Vertex vertex2, String extra) {
Edge edge = new Edge(weight,vertex1,vertex2,extra);
edges.add(edge);
}
public void printVertices() {
for(Vertex vertex : vertices){
System.out.println("ID:" + vertex.getID() + " Name:" + vertex.getName());
}
}
public void printEdges() {
for(Edge edge : edges){
System.out.println("StartVertex:" + edge.getStartVertex() + "ID: "+ edge.getStartVertex().getID() +" EndVertex:" + edge.getTargetVertex()+"ID: "+ edge.getTargetVertex().getID() + "Weight:" + edge.getWeight());
}
}
public Vertex getVertex(Vertex v) {
return v;
}
public Map<Vertex, Double> getNeighbours(Vertex vertex) {
Map<Vertex,Double> neighbors = new HashMap();
Object[] check = edges.toArray();
Object[] check2 = vertices.toArray();
for(int i = 0; i < edges.size(); i++) {
if(((Edge) check[i]).getStartVertex().getID() == vertex.getID()) {
neighbors.put(((Edge) check[i]).getTargetVertex(),((Edge) check[i]).getWeight());
}
//check for
/*else if(((Edge) check[i]).getTargetVertex() == vertex) {
neighbors.put(((Edge) check[i]).getStartVertex(),((Edge) check[i]).getWeight());
}*/
}
for (Entry<Vertex, Double> entry : neighbors.entrySet()) {
System.out.println("ID: " + entry.getKey().getID() + " Value: " + entry.getValue() );
}
return neighbors;
}
}
ShortestPathFinder
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.PriorityQueue;
import java.util.Set;
class ShortestPathFinder {
private Graph graph = new Graph();
private Vertex source = new Vertex(0, null);
private Vertex destination = new Vertex(0,null);
private Map<Vertex,Double> minimumWeightToVertices = new HashMap();
private Map<Vertex,Vertex> previousVertex = new HashMap();
private Set<Vertex> visited = new HashSet();
private Map<Vertex,Double> neighbors = new HashMap();
public Optional<Path> findShortestPath(Graph graph, Vertex source, Vertex destination) {
this.graph = graph;
this.source = graph.getVertex(source);
this.destination = graph.getVertex(destination);
Optional<Path> pathFound = Optional.empty();
//start queue at source vertex
source.setDistance(0);
PriorityQueue<Vertex> priorityQueue = new PriorityQueue<>();
priorityQueue.add(source);
source.setVisited(true);
while( !priorityQueue.isEmpty() ){
// Getting the minimum distance vertex from priority queue
Vertex actualVertex = priorityQueue.poll();
//get Neighbors of source vertex
neighbors = graph.getNeighbours(actualVertex);
//find Neighbor with lowest weight
for(Entry<Vertex, Double> neighbor : neighbors.entrySet()){
Vertex v = neighbor.getKey();
if(v.getID() == destination.getID()) {
minimumWeightToVertices.put(v,v.getDistance());
v.setPredecessor(actualVertex);
previousVertex.put(actualVertex,v);
priorityQueue.add(v);
// found, set pathFound = Optional.of(path)
Path path = new Path();
pathFound = Optional.of(path);
}
else if(visited.contains(v) == false)
{
double newDistance = actualVertex.getDistance() + neighbor.getValue();
//when found min add to minmumWeightToVertices
if( newDistance < v.getDistance() ){
priorityQueue.remove(v);
v.setDistance(newDistance);
minimumWeightToVertices.put(v,newDistance);
v.setPredecessor(actualVertex);
previousVertex.put(actualVertex,v);
priorityQueue.add(v);
System.out.println("Added: " + v.getID());
}
}
}
//When visited add to visited so not visited again
actualVertex.setVisited(true);
visited.add(actualVertex);
//continue getting neighbors with lowest index until destination reached
}
return pathFound;
}
public void getPath() {
//print all info using previous Vertex and print out edge info from it
for (Entry<Vertex, Vertex> entry : previousVertex.entrySet()) {
System.out.println("ID: " + entry.getKey().getID() + " Name: " + entry.getKey().getName() +
" to " + "ID: " + entry.getValue().getID() + " Name: " + entry.getValue().getName());
}
}
}
Edge
public class Edge {
private double weight;
private Vertex startVertex;
private Vertex targetVertex;
private String extra;
public Edge(double weight, Vertex startVertex, Vertex targetVertex, String extra) {
this.weight = weight;
this.startVertex = startVertex;
this.targetVertex = targetVertex;
this.extra = extra;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Vertex getStartVertex() {
return startVertex;
}
public void setStartVertex (Vertex startVertex) {
this.startVertex = startVertex;
}
public Vertex getTargetVertex() {
return targetVertex;
}
public void setTargetVertex(Vertex targetVertex) {
this.targetVertex = targetVertex;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}
Vertex
public class Vertex implements Comparable<Vertex> {
private int ID;
private String name;
private List<Edge> adjacenciesList;
private boolean visited;
private Vertex predecessor;
private double distance = Double.MAX_VALUE;
public Vertex(int ID, String name) { //(Int ID, String name)?
this.ID = ID;
this.name = name;
this.adjacenciesList = new ArrayList<>();
}
public void addNeighbour(Edge edge) {
this.adjacenciesList.add(edge);
}
public String getName() {
return name;
}
public void setID(int ID) {
this.ID = ID;
}
public int getID() {
return ID;
}
public void setName(String name) {
this.name = name;
}
public List<Edge> getAdjacenciesList() {
return adjacenciesList;
}
public void setAdjacenciesList(List<Edge> adjacenciesList) {
this.adjacenciesList = adjacenciesList;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public Vertex getPredecessor() {
return predecessor;
}
public void setPredecessor(Vertex predecessor) {
this.predecessor = predecessor;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
#Override
public String toString() {
return this.name;
}
#Override
public int compareTo(Vertex otherVertex) {
return Double.compare(this.distance, otherVertex.getDistance());
}
}
ReadInput
public class ReadInput {
Vertex[] vertex = new Vertex[25252];
final String DELIMITER = ",";
int indexVertex = 0;
//public Vertex[] readVertices() throws NumberFormatException, IOException {
public Graph readFromStream() throws NumberFormatException, IOException {
Graph graph = new Graph();
//25252 number of elements in Place.txt file
//Delimiter used in CSV file
String line = "";
//Create the file reader
BufferedReader fileReader = new BufferedReader(new FileReader("Place.txt"));
String IDString = null;
String name = null;
int ID = 0;
//Read the file line by line
while ((line = fileReader.readLine()) != null)
{
//Get all tokens available in line
String[] tokens = line.split(DELIMITER);
//for(String token : tokens)
//{
IDString = tokens[0];
name = tokens[1];
ID = Integer.parseInt(IDString);
//}
vertex[indexVertex] = new Vertex(ID,name);
graph.addVertex(ID,name);
//System.out.println(indexVertex +":" + vertex[indexVertex].getID());
indexVertex++;
}
fileReader.close();
//return vertex;
//}
//public Edge[] readEdges() throws NumberFormatException, IOException {
Edge[] edge = new Edge[127807];
int indexEdge = 0;
String line2 = "";
BufferedReader fileReader2 = new BufferedReader(new FileReader("Road.txt"));
String valueString = null;
String vertex1IDName = null;
String vertex2IDName = null;
String extra = null;
float value = 0;
int vertex1ID = 0;
int vertex2ID = 0;
//Read the file line by line
while ((line2 = fileReader2.readLine()) != null)
{
//Get all tokens available in line
String[] tokens2 = line2.split(DELIMITER);
//for(String token1 : tokens2)
//{
vertex1IDName = tokens2[0];
vertex2IDName = tokens2[1];
valueString = tokens2[2];
if(tokens2.length - 1 == 3) {
extra = tokens2[tokens2.length - 1];
}
else {
extra = "";
}
vertex1ID = Integer.parseInt(vertex1IDName);
vertex2ID = Integer.parseInt(vertex2IDName);
value = Float.parseFloat(valueString);
//adds all edges with null vertex names, need to account for edges that connect to actual vertices?
Vertex vertex1 = new Vertex(vertex1ID,"null");
Vertex vertex2 = new Vertex(vertex2ID,"null");
graph.addEdge(value,vertex1, vertex2, extra);
}
fileReader2.close();
return graph;
//return edge;
}
public Vertex calcualteDestination() {
Scanner scanUserInput = new Scanner(System.in);
System.out.println("Enter the Destination Name:");
String destinationName = scanUserInput.nextLine();
scanUserInput.close();
Vertex Destination = new Vertex(0,null);
for(int i = 0; i<indexVertex; i++) {
if(destinationName.equals(vertex[i].getName())){
Destination.setID(vertex[i].getID());
Destination.setName(vertex[i].getName());
}
}
return Destination;
}
public Vertex calculatesSource() {
Scanner scanUserInput = new Scanner(System.in);
System.out.println("Enter the Source Name:");
String sourceName = scanUserInput.nextLine();
Vertex Source = new Vertex(0, null);
for(int i = 0; i<indexVertex; i++) {
if(sourceName.equals(vertex[i].getName())){
Source.setID(vertex[i].getID());
Source.setName(vertex[i].getName());
}
}
return Source;
}
}
Main
ppublic class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
ReadInput graphReader = new ReadInput();
Graph graph = graphReader.readFromStream();
Vertex source = graphReader.calculatesSource();
Vertex destination = graphReader.calcualteDestination();
//graph.printEdges();
//graph.printVertices();
ShortestPathFinder finder = new ShortestPathFinder();
Optional<Path> possiblePath = finder.findShortestPath(graph,source,destination);
if(possiblePath.isPresent() == false) {
System.out.println("No path found");
}
else {
System.out.println("Shortest path:");
finder.getPath();
}
}
}
You should immediately return pathFound when you find a path.
if (v.getID() == destination.getID()) {
...
return Optional.of(path);
}
Otherwise, you are not only wasting time exploring the rest of the graph, but you may even find a different, longer path to the target and overwrite the shortest path with that one.
It's also a bit odd that at this point, path is just new Path(). It seems like you only use this to mark the Optional as non-empty while leaving the actual information about the path in the ShortestPathFinder's previousVertex map. Better put the path information directly into the Path object, unrolling it in a similar way as you do in getPath.
Currently, only the final vertex is being printed, and the minimum distance seems to evaluate to infinity. I can't seem to find where the issue is with vertex's not being added to the "shortest path" ArrayList. I would like to also print out all the edges that are taken by the path. Any suggestions are very welcome Below is my full code, thanks!
Edit: I have edited my classes as recommended by sprinter.
An error is in my Graph class, in my getNeighbours() method. The information regarding the source is being added as a neighbor, even though I'm trying to get it's neighbors.
I am also not sure how to print out the edge info, along with the Vertex info.
Any recommendations are greatly appreciated!
ShortestPathFinder
class ShortestPathFinder {
private Graph graph = new Graph();
private Vertex source = new Vertex(0, null);
private Vertex destination = new Vertex(0,null);
private Map<Vertex,Double> minimumWeightToVertices = new HashMap();
private Map<Vertex,Vertex> previousVertex = new HashMap();
private Set<Vertex> visited = new HashSet();
private Map<Vertex,Double> neighbors = new HashMap();
public Optional<Path> findShortestPath(Graph graph, Vertex source, Vertex destination) {
this.graph = graph;
this.source = graph.getVertex(source);
this.destination = graph.getVertex(destination);
Optional<Path> pathFound = Optional.empty();
//start queue at source vertex
source.setDistance(0);
PriorityQueue<Vertex> priorityQueue = new PriorityQueue<>();
priorityQueue.add(source);
source.setVisited(true);
while( !priorityQueue.isEmpty() ){
// Getting the minimum distance vertex from priority queue
Vertex actualVertex = priorityQueue.poll();
//get Neighbors of source vertex
neighbors = graph.getNeighbours(source);
//find Neighbor with lowest weight
for(Entry<Vertex, Double> neighbor : neighbors.entrySet()){
Vertex v = neighbor.getKey();
if(v == destination) {
minimumWeightToVertices.put(v,v.getDistance());
v.setPredecessor(actualVertex);
previousVertex.put(actualVertex,v);
priorityQueue.add(v);
// found, set pathFound = Optional.of(path)
Path path = new Path();
pathFound = Optional.of(path);
}
else if(visited.contains(v) == false)
{
double newDistance = actualVertex.getDistance() + neighbor.getValue();
//when found min add to minmumWeightToVertices
if( newDistance < v.getDistance() ){
priorityQueue.remove(v);
v.setDistance(newDistance);
minimumWeightToVertices.put(v,newDistance);
v.setPredecessor(actualVertex);
previousVertex.put(actualVertex,v);
priorityQueue.add(v);
System.out.println("Added: " + v.getID());
}
}
}
//When visited add to visited so not visited again
actualVertex.setVisited(true);
visited.add(actualVertex);
//continue getting neighbors with lowest index until destination reached
}
return pathFound;
}
public void getPath() {
//print all info using previous Vertex and print out edge info from it
for (Entry<Vertex, Vertex> entry : previousVertex.entrySet()) {
System.out.println("ID: " + entry.getKey().getID() + " Name: " + entry.getKey().getName() +
" to " + "ID: " + entry.getValue().getID() + " Name: " + entry.getValue().getName());
}
}
}
Graph
class Graph {
private final Set<Vertex> vertices = new HashSet<Vertex>();
private final Set<Edge> edges = new HashSet<Edge>();
public void addVertex(int id, String name) {
Vertex vertex = new Vertex(id,name);
vertices.add(vertex);
//System.out.println("ID:" + vertex.getID() + "Name:" + vertex.getName());
}
public void addEdge(double weight, Vertex vertex1, Vertex vertex2, String extra) {
Edge edge = new Edge(weight,vertex1,vertex2,extra);
edges.add(edge);
}
public void printVertices() {
for(Vertex vertex : vertices){
System.out.println("ID:" + vertex.getID() + " Name:" + vertex.getName());
}
}
public void printEdges() {
for(Edge edge : edges){
System.out.println("StartVertex:" + edge.getStartVertex() +" EndVertex:" + edge.getTargetVertex()+ "Weight:" + edge.getWeight());
}
}
public Vertex getVertex(Vertex v) {
return v;
}
public Map<Vertex, Double> getNeighbours(Vertex vertex) {
Map<Vertex,Double> neighbors = new HashMap();
Object[] check = edges.toArray();
for(int i = 0; i < edges.size(); i++) {
if(((Edge) check[i]).getStartVertex().getID() == vertex.getID()) {
neighbors.put(((Edge) check[i]).getTargetVertex(),((Edge) check[i]).getWeight());
}
else if(((Edge) check[i]).getTargetVertex().getID() == vertex.getID()) {
neighbors.put(((Edge) check[i]).getStartVertex(),((Edge) check[i]).getWeight());
}
}
return neighbors;
}
}
Edge
public class Edge {
private double weight;
private Vertex startVertex;
private Vertex targetVertex;
private String extra;
public Edge(double weight, Vertex startVertex, Vertex targetVertex, String extra) {
this.weight = weight;
this.startVertex = startVertex;
this.targetVertex = targetVertex;
this.extra = extra;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Vertex getStartVertex() {
return startVertex;
}
public void setStartVertex (Vertex startVertex) {
this.startVertex = startVertex;
}
public Vertex getTargetVertex() {
return targetVertex;
}
public void setTargetVertex(Vertex targetVertex) {
this.targetVertex = targetVertex;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}
Vertex
public class Vertex implements Comparable<Vertex> {
private int ID;
private String name;
private List<Edge> adjacenciesList;
private boolean visited;
private Vertex predecessor;
private double distance = Double.MAX_VALUE;
public Vertex(int ID, String name) { //(Int ID, String name)?
this.ID = ID;
this.name = name;
this.adjacenciesList = new ArrayList<>();
}
public void addNeighbour(Edge edge) {
this.adjacenciesList.add(edge);
}
public String getName() {
return name;
}
public void setID(int ID) {
this.ID = ID;
}
public int getID() {
return ID;
}
public void setName(String name) {
this.name = name;
}
public List<Edge> getAdjacenciesList() {
return adjacenciesList;
}
public void setAdjacenciesList(List<Edge> adjacenciesList) {
this.adjacenciesList = adjacenciesList;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public Vertex getPredecessor() {
return predecessor;
}
public void setPredecessor(Vertex predecessor) {
this.predecessor = predecessor;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
#Override
public String toString() {
return this.name;
}
#Override
public int compareTo(Vertex otherVertex) {
return Double.compare(this.distance, otherVertex.getDistance());
}
}
Main
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
ReadInput graphReader = new ReadInput();
Graph graph = graphReader.readFromStream();
Vertex source = graphReader.calculatesSource();
Vertex destination = graphReader.calcualteDestination();
//graph.printEdges();
//graph.printVertices();
ShortestPathFinder finder = new ShortestPathFinder();
Optional<Path> possiblePath = finder.findShortestPath(graph,source,destination);
if(possiblePath.isPresent() == false) {
System.out.println("No path found");
}
else {
System.out.println("Shortest path:");
finder.getPath();
}
}
}
ReadInputIn
public class ReadInput {
Vertex[] vertex = new Vertex[25252];
final String DELIMITER = ",";
int indexVertex = 0;
//public Vertex[] readVertices() throws NumberFormatException, IOException {
public Graph readFromStream() throws NumberFormatException, IOException {
Graph graph = new Graph();
//25252 number of elements in Place.txt file
//Delimiter used in CSV file
String line = "";
//Create the file reader
BufferedReader fileReader = new BufferedReader(new FileReader("Place.txt"));
String IDString = null;
String name = null;
int ID = 0;
//Read the file line by line
while ((line = fileReader.readLine()) != null)
{
//Get all tokens available in line
String[] tokens = line.split(DELIMITER);
//for(String token : tokens)
//{
IDString = tokens[0];
name = tokens[1];
ID = Integer.parseInt(IDString);
//}
vertex[indexVertex] = new Vertex(ID,name);
graph.addVertex(ID,name);
//System.out.println(indexVertex +":" + vertex[indexVertex].getID());
indexVertex++;
}
fileReader.close();
//return vertex;
//}
//public Edge[] readEdges() throws NumberFormatException, IOException {
Edge[] edge = new Edge[127807];
int indexEdge = 0;
String line2 = "";
BufferedReader fileReader2 = new BufferedReader(new FileReader("Road.txt"));
String valueString = null;
String vertex1IDName = null;
String vertex2IDName = null;
String extra = null;
float value = 0;
int vertex1ID = 0;
int vertex2ID = 0;
//Read the file line by line
while ((line2 = fileReader2.readLine()) != null)
{
//Get all tokens available in line
String[] tokens2 = line2.split(DELIMITER);
//for(String token1 : tokens2)
//{
vertex1IDName = tokens2[0];
vertex2IDName = tokens2[1];
valueString = tokens2[2];
if(tokens2.length - 1 == 3) {
extra = tokens2[tokens2.length - 1];
}
else {
extra = "";
}
vertex1ID = Integer.parseInt(vertex1IDName);
vertex2ID = Integer.parseInt(vertex2IDName);
value = Float.parseFloat(valueString);
//graph.addEdge(value, vertex1ID, vertex2ID, extra);
//}
//System.out.println("value: "+ value + " vertex1ID:"+ vertex1ID +" vertex2ID:"+ vertex2ID+ " extra:" + extra);
//if vertex 1 name or vertex 2 name in vertex.getID()
for(int i = 0; i< indexVertex; i++) {
if(vertex1ID == vertex[i].getID() || vertex2ID == vertex[i].getID()){
for(int j = 0; j< indexVertex; j++) {
if(vertex2ID == vertex[j].getID() || vertex1ID == vertex[j].getID()) {
//vertex[i].addNeighbour(edge[indexEdge] = new Edge(value,vertex[i],vertex[j],extra));
graph.addEdge(value, vertex[i], vertex[j], extra); //newline for constructing graph
//System.out.println("Edge added: "+ vertex1ID +" = " + vertex[i].getID() + " "+ vertex2ID + " = " + vertex[j].getID());
indexEdge++;
}
}
}
}
}
fileReader2.close();
return graph;
//return edge;
}
public Vertex calcualteDestination() {
Scanner scanUserInput = new Scanner(System.in);
System.out.println("Enter the Destination Name:");
String destinationName = scanUserInput.nextLine();
scanUserInput.close();
Vertex Destination = new Vertex(0,null);
for(int i = 0; i<indexVertex; i++) {
if(destinationName.equals(vertex[i].getName())){
Destination.setID(vertex[i].getID());
Destination.setName(vertex[i].getName());
}
}
return Destination;
}
public Vertex calculatesSource() {
Scanner scanUserInput = new Scanner(System.in);
System.out.println("Enter the Source Name:");
String sourceName = scanUserInput.nextLine();
Vertex Source = new Vertex(0, null);
for(int i = 0; i<indexVertex; i++) {
if(sourceName.equals(vertex[i].getName())){
Source.setID(vertex[i].getID());
Source.setName(vertex[i].getName());
}
}
return Source;
}
}
I have a few suggestions for how you might consider restructuring your code to make it easier to debug:
You are currently storing shortest path information with the vertex. This is not good design. Better would be to have the information on the graph separate (and immutable - i.e. no setters) from the volatile information on shortest paths.
You should have a Graph class that holds all vertex and edge sets and exposes only methods to interrogate the graph. You should be able unit test that the graph is set up as you expect after input independently of testing the shortest path algorithm
The path info should be encapsulated within your ShortestPath class - there should be no need to expose that outside the class. You should be able to unit test that independently of the code to read graphs
Most of the logic in your main method should be in a separate classes such as GraphReader - these should be unit testable
I suggest you make those changes - I'm confident restructuring the code in this way will make the problem much more obvious.
Here's a possible design to give you some ideas of what I'm talking about.
class Vertex {
private final int id;
private final String name;
}
class Edge {
private final Vertex vertex1;
private final Vertex vertex2;
private final double weight;
}
class Graph {
private final Set<Vertex> vertices;
private final Set<Edge> edges;
public void addVertex(int id, String name) {...}
public void addEdge(int vertex1, int vertex2, double weight) {...}
public Vertex getVertex(int id) {...}
public Map<Vertex,Double> getNeighbours(Vertex vertex) {...}
}
class GraphReader {
public Graph readFromStream(InputStream input) {...}
}
class Path {
private final List<Vertex> steps;
}
This means you can encapsulate the temporary information you need to hold while building the shortest path into a separate class: vertices and edges don't need to hold that information.
class ShortestPathFinder {
private final Graph graph;
private final Vertex start;
private final Vertex end;
private final Map<Vertex,Double> minimumWeightToVertices;
private final Map<Vertex,Vertex> previousVertex;
private final Set<Vertex> visited;
public ShortestPathFinder(Graph graph, int start, int end) {
this.graph = graph;
this.start = graph.getVertex(start);
this.end = graph.getVertex(end);
...
}
public boolean hasPath() {...}
public Path getPath() {...}
}
public static void main(String[] args) {
GraphReader graphReader = new Graph();
Graph graph = graphReader.readFromStream(System.in);
ShortestPathFinder finder = new ShortestPathFinder(graph, 1, 10);
if (finder.hasPath())
System.out.println("Shortest path " + finder.getPath());
}
I'm making console app for Planting house. House has 6 rows and each row has 25 Sections. I built this structure using arraylists of rows and sections. Now I want to add plants to the section from user input. I
I have tried multiple ways to do it creating different methods which you can see in the comments but nothing is working, the Object Plant is either not getting created or not getting added to ArrayList plants.
public class Section {
private int number;
private List<TomatoPlant> plants;
public int getNumber() {
return number;
}
public Section(int number, List<TomatoPlant> plants) {
this.number = number;
this.plants = plants;
}
public Section(int number){
this.number=number;
//this.addPlants();
this.plants= new ArrayList<>();
}
public List getPlants() {
return this.plants;
}
public void addPlants(Cocktailtomatos cocktailtomato) {
//this.plants= new ArrayList<>();
this.plants.add(cocktailtomato);
this.plants.add(Cocktailtomatos.createCocktailtomato("ss", "A", 1));
}
#Override
public String toString() {
return "Section{" +
"number=" + number +
", plants=" + plants +
'}';
}
public void addPlant(String id, String row, int sectionnumber) {
Cocktailtomatos cocktailtomato = new Cocktailtomatos(id, row, sectionnumber, true, false, false, 0, 10);
this.addPlants(cocktailtomato);
}
}
public class Manager {
private static Manager ourInstance = new Manager();
public static Manager getInstance() {
return ourInstance;
}
private Manager() {
}
Planthouse planthouse = new Planthouse();
public void addCocktailTomato(){
Scanner scanner = new Scanner(System.in);
System.out.println("Input Id:");
String id = scanner.nextLine();
System.out.println("Input Row");
String row = scanner.nextLine();
System.out.println("Input sectionnumber");
Integer sectionnumber = scanner.nextInt();
//Cocktailtomatos cocktailtomato = Cocktailtomatos.createCocktailtomato(id, row, sectionnumber);
//cocktailtomato.setId(row + sectionnumber + "_" + id);
//planthouse.getRow(row).getSection(sectionnumber).getPlants().add(cocktailtomato);
//System.out.println("ID: ");
//Cocktailtomatos cocktailtomato = new Cocktailtomatos(id, row, sectionnumber, true, false, false, 0, 10);
//planthouse.getRow(row).getSection(sectionnumber).getPlants().add(cocktailtomato);
//Cocktailtomatos cocktailtomato = Cocktailtomatos.createCocktailtomato(id, row, sectionnumber);
//planthouse.getRow(row).getSection(sectionnumber).addPlants(cocktailtomato);
planthouse.getRow(row).getSection(sectionnumber).addPlant(id, row, sectionnumber);
//this.getPlantlist();
}
public int getPlantlist() {
Scanner scanner = new Scanner(System.in);
System.out.println("Input row:");
String row = scanner.nextLine();
System.out.println("Input sectionnumber:");
Integer sectionnumber = scanner.nextInt();
//return planthouse.getRow(row).getSection(sectionnumber).getPlants();
//System.out.println(planthouse.getRow(row).getSection(sectionnumber).getPlants().size());
System.out.println(planthouse.getRows());
//System.out.println(planthouse.getRow("A").getSections().size());
//for(int i=0; i<planthouse.getRow("A").getSections().size(); i++){
//System.out.println(planthouse.getRow("A").getSections().get(i).getPlants());
//}
//for(int i=0; i<planthouse.getRows().size(); i++){
// System.out.println(planthouse.getRows().get(i));
// }
return planthouse.getRow(row).getSection(sectionnumber).getPlants().size();
}
}
public class Planthouse {
private ArrayList<Row> rows = new ArrayList<>();
public Planthouse(){
this.initRows();
}
public Planthouse(ArrayList<Row> rows) {
this.setRows(rows);
}
public ArrayList<Row> getRows() {
return rows;
}
private void initRows() {
this.rows= new ArrayList<>();
this.rows.add(new Row("A"));
this.rows.add(new Row("B"));
this.rows.add(new Row("C"));
this.rows.add(new Row("D"));
this.rows.add(new Row("E"));
this.rows.add(new Row("F"));
}
public void setRows(ArrayList<Row> rows) {
this.rows = rows;
}
public void printPlanthouse(){
for(Row row: rows) {
System.out.println(row.getId());
row.printSections();
}
}
public Row getRow(String rowId) {
Row row = new Row(rowId);
return row;
}
public void addPlant(){
}
public Section getSection(Row row, Section section) {
Planthouse planthouse = new Planthouse();
planthouse.getRow(row.getId()).getSection(section.getNumber());
return section;
}
}
public class Row {
private String id;
private ArrayList<Section> sections;
public Row(String id) {
this.id = id;
this.initSections();
}
public Row(String id, ArrayList<Section> sections) {
this.id = id;
this.setSections(sections);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<Section> getSections() {
return sections;
}
public void setSections(ArrayList<Section> sections) {
this.sections = sections;
}
public void initSections() {
this.sections = new ArrayList<>();
for (int i = 1; i <=25; i++) {
this.sections.add(new Section(i));
}
}
public void printSections() {
for (Section section : sections) {
System.out.println(section.getNumber());
}
}
public Row(){
}
#Override
public String toString() {
return "Row{" +
"id='" + id + '\'' +
", sections=" + sections +
'}';
}
public Section getSection(int sectionnumber){
//Section section = new Section(sectionnumber);
Section section = sections.get(sectionnumber-1);
return section;
}
}
Method getPlantList() prints out all rows with its sections and each section with its plants, and after user adds a plant into section these sections are being printed empty (without plants). So I come to conclusion that either plant is not created or not added to an arraylist. Can someone suggest me where is the problem? Thank you.
The current getRow creates everytime a new Row not placed in the entire data hierarchy.
public Row getRow(String rowId) {
for (Row row : rows) {
if (row.getId().equals(rowId)) {
return row;
}
}
// Either throw new IllegalArgumentException(); or:
Row row = new Row(rowId);
rows.add(row);
return row;
}
Instead, or additionally to a list you might want to use a Map from rowId to a Row.
Map<String, Row> rowMap = new HashMap<>();
Map<String, Row> rowMap = new TreeMap<>(); // Sorted
Map<String, Row> rowMap = new LinkHashMap<>(); // In order of insertion, chronological
String rowId = "A";
rowMap.put(rowId, row);
Row row = rowMap.get(rowId);
I have three orders with items what customer bought from shop.
below is the model of lines on the Order.
public class ShopOrderItem {
private String name;
private String itemcode;
private int count;
private double price;
private String taxRate;
public ShopOrderItem() {
super();
}
public ShopOrderItem(String name, String itemcode, int count, double price,
String taxRate) {
super();
this.name = name;
this.itemcode = itemcode;
this.count = count;
this.price = price;
this.taxRate = taxRate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getItemcode() {
return itemcode;
}
public void setItemcode(String itemcode) {
this.itemcode = itemcode;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getTaxRate() {
return taxRate;
}
public void setTaxRate(String taxRate) {
this.taxRate = taxRate;
}
}
and below is how to get the 3 orders.
public class testList {
ShopOrderItem a = new ShopOrderItem("apple","001",2,(double)4.00,"0.17");
ShopOrderItem b = new ShopOrderItem("banana","002",1,(double)2.00,"0.17");
ShopOrderItem c = new ShopOrderItem("light","003",1,(double)30.00,"0.17");
ShopOrderItem d = new ShopOrderItem("apple","001",5,(double)4.00,"0.17");
ShopOrderItem e = new ShopOrderItem("light","003",10,(double)30.00,"0.17");
ShopOrderItem f = new ShopOrderItem("apple","001",1,(double)4.00,"0.17");
ShopOrderItem g = new ShopOrderItem("pen","004",3,(double)3.00,"0.17");
List<ShopOrderItem> orderA = new ArrayList<ShopOrderItem>();
orderA.add(a);
orderA.add(b);
orderA.add(c);
List<ShopOrderItem> orderB = new ArrayList<ShopOrderItem>();
orderB.add(d);
orderB.add(e);
List<ShopOrderItem> orderC = new ArrayList<ShopOrderItem>();
orderC.add(f);
orderC.add(g);
}
I want to merge this 3 List to one List.
when same name ,add the count.
for example,my new list will have one line ,name is apple, and count is three orders' apple 's sum.
how i merge these three lists?
Usage: groupByNameAndSumCount(orderA, orderB, orderC)
static List<ShopOrderItem> groupByNameAndSumCount(List<ShopOrderItem>... orders) {
List<ShopOrderItem> merged = new ArrayList<>();
for (List<ShopOrderItem> order : orders) {
merged.addAll(order);
}
// group all by name as this is our invariant
HashMap<String, ShopOrderItem> grouped = new HashMap<>();
for (ShopOrderItem item : merged) {
String name = item.getName();
if (grouped.containsKey(name)) {
ShopOrderItem current = grouped.get(name);
// sum count
current.setCount(current.getCount() + item.getCount());
} else {
grouped.put(name, item);
}
}
// reusing to reduce memory footprint
merged.clear();
// prepare result
for (String key : grouped.keySet()) {
merged.add(grouped.get(key));
}
return merged;
}
Hope it helps, sir!
you can add the 3 lists to one list, sort it and then put them in a map. then turn the map into a list.
List<ShopOrderItem> merged = new ArrayList<ShopOrderItem>();
merged.addAll(orderA);
merged.addAll(orderB);
merged.addAll(orderC);
Collections.sort(merged, new Comparator<ShopOrderItem>() {
#Override
public int compare(ShopOrderItem o1, ShopOrderItem o2) {
return (Integer.parseInt(o1.getItemcode()) - Integer.parseInt(o2.getItemcode()));
}
});
HashMap<String,Integer> map = new HashMap<String,Integer>();
for (ShopOrderItem shopOrderItem : merged) {
if(map.containsKey(shopOrderItem.getItemcode())){
int current = map.get(shopOrderItem.getItemcode());
current+=shopOrderItem.getCount();
map.remove(shopOrderItem.getItemcode());
map.put(shopOrderItem.getItemcode(), current);
}else{
map.put(shopOrderItem.getItemcode(), shopOrderItem.getCount());
}
}
List<ShopOrderItem> result = new ArrayList<ShopOrderItem>();
Set<Entry<String,Integer>> set = map.entrySet();
for (Entry<String, Integer> entry : set) {
if(entry.getKey().equals(a.getItemcode())){
ShopOrderItem t = new ShopOrderItem(a.getName(), a.getItemcode(), entry.getValue(), a.getPrice(), a.getTaxRate());
result.add(t);
}else if(entry.getKey().equals(b.getItemcode())){
ShopOrderItem t = new ShopOrderItem(b.getName(), b.getItemcode(), entry.getValue(), b.getPrice(), b.getTaxRate());
result.add(t);
}
else if(entry.getKey().equals(c.getItemcode())){
ShopOrderItem t = new ShopOrderItem(c.getName(), c.getItemcode(), entry.getValue(), c.getPrice(), c.getTaxRate());
result.add(t);
}
else if(entry.getKey().equals(g.getItemcode())){
ShopOrderItem t = new ShopOrderItem(g.getName(), g.getItemcode(), entry.getValue(), g.getPrice(), g.getTaxRate());
result.add(t);
}
}
Using Java 8:
Collection<ShopOrderItem> result = Stream.of(orderA, orderB, orderC)
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(
ShopOrderItem::getItemcode,
Collectors.reducing(new ShopOrderItem(), Use::merge)
))
.values();
private static ShopOrderItem merge(ShopOrderItem s1, ShopOrderItem s2)
{
return new ShopOrderItem(s2.getName(), s2.getItemcode(), s1.getCount() + s2.getCount(), s2.getPrice(), s2.getTaxRate());
}
I need to implement the method Customer3.toArray().
Customer3 is the ADT and Linked List Node (which was given to me by the teacher) and we aren't allowed to change. Just implement the toArray() method. To make it simple, I already know that there will be 64 customer objects in the List so I create an array of 64 elements.
I'm not exactly sure how to do this for LinkedLists. I was hoping maybe someone could show me a simple way of converting it.
Code:
public class
Customer3
implements java.io.Serializable
{
Customer3 next;
String ID;
String name;
String state;
String salesID;
public Customer3() {
ID = null; name = null; state = null; salesID = null;
next = null;
}
public Customer3(String i, String n, String s, String si){
ID = i;
name = n;
state = s;
salesID = si;
next = null;
}
public Customer3 getNext() { return next; }
public String getID() { return ID; }
public String getName() { return name; }
public String getState() { return state; }
public String getSalesID() { return salesID; }
public void setNext(Customer3 n) { next = n; }
public void setName(String n) { name = n; }
public void setState(String s) { state = s; }
public void setSalesID (String si) { salesID = si; }
public String toString() { return ID + " " + name + " " + state + " " + salesID; }
public Customer3 add(Customer3 h) {
if (h == null) return this;
Customer3 temp = h;
while (temp.next != null) // look for the end of the list
temp = temp.next;
temp.next = this; // append the new node to the end
return h;
} // add
public void show() {
System.out.println(this);
if (next != null) next.show();
} // show
public Object [] toArray()
{
Object [] temp=null;
temp = new Object[64];
return temp;
} // toArray
} //
try
public Object[] toArray() {
int size = 1;
Customer3 curr = this;
while (curr.next != null) {
size++;
curr = curr.next;
}
Object[] arr = new Object[size];
arr[0] = this;
for (int i = 1; i < size; i++) {
arr[i] = ((Customer3)arr[i - 1]).next;
}
return arr;
}