1

Sorry if this is a duplicate, but been struggling with other solutions. I'm making a pathfinding application for a project.

I wish to sort my arraylist of Edges that allows me to have import/export. The export doesn't sort them the way the import expects so technically works, but throws an error.

First column is start node, 2nd column is end node and 3rd column is irrelevant but is distance. I need to sort by the first and 2nd nodes to have them in order.

Current output:

6 8 5.0
7 8 1.0
7 9 5.0
3 5 3.0
3 4 1.0
8 9 1.0
1 2 5.0
1 3 2.0
1 4 4.0
4 9 10.0
4 5 1.0
4 7 6.0
2 3 4.0
2 6 3.0
5 7 6.0

Wanted Output:

1 2 5.0
1 3 2.0
1 4 4.0
2 3 4.0
2 6 3.0 
...

My export file code, just trying to add Comparable to it, but was having issues.

 public String exportToFile(String file) throws IOException {
    FileWriter fileWriter;
    ArrayList<Edge> edgeArrayList = new ArrayList<Edge>();
    dijkstra.copyEdge(edgeArrayList);
    String space = " ", fileExported = "File Exported";

    try {
        fileWriter = new FileWriter(file);
    } catch (IOException e) {
        return "File Not Found";
    }

    fileWriter.write(nodes.size() + "" + '\n');
    for (Node node : nodes) {
        fileWriter.write(node.name + space + node.x + space + node.y + '\n');
    }

    fileWriter.write(edgeArrayList.size() + "" + '\n');
    for (Edge edge : edgeArrayList) {
        fileWriter.write(edge.sourceNode.name + space + edge.destinationNode.name + space + edge.nodeWeight + '\n');
    }

    fileWriter.close();
    return fileExported;
}

Thanks

Edit - Added Edge class

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;

import java.util.Comparator;

public class Edge {
    public Node sourceNode;
    public Node destinationNode;
    public double nodeWeight;
    public int roadType;
    private final Line line;
    private final Text text;

    public Edge(Node source, Node destination, double weight) {
        line = new Line();
        text = new Text();
        sourceNode = source;
        destinationNode = destination;
        nodeWeight = weight;

        DoubleProperty startX = new SimpleDoubleProperty(source.x);
        DoubleProperty startY = new SimpleDoubleProperty(source.y);
        DoubleProperty endX = new SimpleDoubleProperty(destination.x);
        DoubleProperty endY = new SimpleDoubleProperty(destination.y);
        line.startXProperty().bind(startX);
        line.startYProperty().bind(startY);
        line.endXProperty().bind(endX);
        line.endYProperty().bind(endY);
        startX.bind(source.getCircle().centerXProperty());
        startY.bind(source.getCircle().centerYProperty());
        endX.bind(destination.getCircle().centerXProperty());
        endY.bind(destination.getCircle().centerYProperty());
        text.setText(weight + "");
        text.xProperty().bind((startX.add(endX)).divide(2));
        text.yProperty().bind((startY.add(endY)).divide(2));
    }

    public Line getLine() {
        return line;
    }

    public Text getText() {
        return text;
    }

    public String toString() {
        return String.format("(%s -> %s,%f)", sourceNode.name, destinationNode.name, nodeWeight);
    }
}

Edit#2 - added Node class

public class Node {

    public double x, y;
    public String name;
    public boolean isVisited;
    public Circle circle;
    public Text text;
    LinkedList<Edge> edges;

    public Node(double x, double y, String name) {
        circle = new Circle(10);
        circle.setFill(Color.WHITE);
        circle.setStroke(Color.BLACK);
        text = new Text(name);
        this.x = x;
        this.y = y;
        this.name = name;
        isVisited = false;
        edges = new LinkedList<>();
    }

    public boolean isVisited() {
        return isVisited;
    }

    public void visitNode() {
        isVisited = true;
    }

    public void leaveNode() {
        isVisited = false;
    }

    public Circle getCircle(double scale) {
        circle.setCenterX(x * scale);
        circle.setCenterY(y * scale);
        return circle;
    }

    public Circle getCircle() {
        return circle;
    }

    public Text getText() {
        text.layoutXProperty().bind(circle.centerXProperty().add(-text.getLayoutBounds().getWidth() / 2));
        text.layoutYProperty().bind(circle.centerYProperty().add(5));
        return text;
    }
}
3
  • @Abra sorry first proper question on here. Edited. OTher people solutions have always worked for me :) Commented Apr 6, 2021 at 17:55
  • 1
    I see a potential problem in your code. Class Edge contains members that are Nodes and class Node contains a list of Edges - even though member edges is never used in class Node. Are you certain that class Node requires the edges member? Commented Apr 6, 2021 at 18:08
  • @Abra i use the Linked list edges in my Dijkstra Algorithm class. I like your original response its very logical so giving that a go currently :) Commented Apr 6, 2021 at 18:13

3 Answers 3

3

Hopefully, I correctly guessed the code of your Edge class.

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Edge {
    private int  start;
    private int  end;
    private float  distance;

    public Edge(int start, int end, float distance) {
        this.start = start;
        this.end = end;
        this.distance = distance;
    }

    public String toString() {
        return String.format("%d %d %f", start, end, distance);
    }

    public static void main(String[] args) {
        List<Edge> edges = new ArrayList<>();
        edges.addAll(List.of(new Edge(6, 8, 5.0f),
                             new Edge(7, 8, 1.0f),
                             new Edge(7, 9, 5.0f),
                             new Edge(3, 5, 3.0f),
                             new Edge(3, 4, 1.0f),
                             new Edge(8, 9, 1.0f),
                             new Edge(1, 2, 5.0f),
                             new Edge(1, 3, 2.0f),
                             new Edge(1, 4, 4.0f),
                             new Edge(4, 9, 10.0f),
                             new Edge(4, 5, 1.0f),
                             new Edge(4, 7, 6.0f),
                             new Edge(2, 3, 4.0f),
                             new Edge(2, 6, 3.0f),
                             new Edge(5, 7, 6.0f)));

        Comparator<Edge> comp = new Comparator<Edge>() {
            
            @Override
            public int compare(Edge e1, Edge e2) {
                if (e1.start > e2.start) {
                    return 1;
                }
                else if (e1.start < e2.start) {
                    return -1;
                }
                else {
                    if (e1.end > e2.end) {
                        return 1;
                    }
                    else if (e1.end < e2.end) {
                        return -1;
                    }
                    else {
                        return 0;
                    }
                }
            }
        };
        edges.sort(comp);
        edges.forEach(System.out::println);
    }
}

Running the above code produces the following output:

1 2 5.000000
1 3 2.000000
1 4 4.000000
2 3 4.000000
2 6 3.000000
3 4 1.000000
3 5 3.000000
4 5 1.000000
4 7 6.000000
4 9 10.000000
5 7 6.000000
6 8 5.000000
7 8 1.000000
7 9 5.000000
8 9 1.000000
Sign up to request clarification or add additional context in comments.

1 Comment

thank you, added my edge class will give this a go!
3

You need to implement a Comparator for the edge. Since I don't have your edge code I can'b be exact, but it would look something like:

Comparator<Edge> comparator = new Comparator<Edge>() {

    @Override
    public int compare(Edge a, Edge b) {
        if (a.startNode.equals(b.startNode)) {
            return a.endNode.compareTo(b.endNode);
        }
            
        return a.startNode.compareTo(b.startNode);
    }
};

Then you just sort your list

Collections.sort(list, compartor)

2 Comments

thanks for reply, will try - added edge class to question
You'll likely just need to replace startNode and endNode with the identifiers for those nodes. Just leverage the existing compareTo functionality for the primitives.
2
import java.util.Comparator;

public class EdgeComparator implements Comparator<Edge> {
    @Override
    public int compare(Edge e1, Edge e2) {
        if (e1.start == e2.start) {
            return e1.end - e2.end;
        } else {
            return e1.start - e2.start;
        }
    }
}

And then:

edgeArrayList.sort(new EdgeComparator());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.