Search code examples
javaalgorithmdesign-patternscollectionsjava-8

I read a txt file to Java and I want to make it be encoded as edges where each edges is a pair of nodes(DFS)


The text file looks like: 0 1

0 2

0 3

1 133

1 194

2 20

2 115

2 116

5 231.....

So what I wanna do is read my txt file and store each line content(because each edge is made by a pair of nodes) in an linked list, I tried this:

import java.io.*;
import java.util.*;


public class readfile{



 public Scanner x;
  public void openFile(){
    try{
      x = new Scanner(new File("facebook_combined.txt"));
    }

catch(Exception e){
  System.out.println("could not open file");
}
}

  public void readFile(){
    LinkedList<Integer,Integer> adj = new LinkedList<Integer,Integer>();
    while(x.hasNext()){
      String a = x.next();
      int resa = Integer.parseInt(a);       
      String b = x.next();
      int resb = Integer.parseInt(b);
      adj.add(resa, resb);
      System.out.println(adj);
    }
  }

  public void closeFile(){
    x.close();
  }
}
class Main {
  public static void main(String[] args) {
    readfile r = new readfile();
    r.openFile();
    r.readFile();
    r.closeFile();
  }
}

But it's return an error that linked-list only allow one type which means I can't store a pair of nodes that is connected to each other.

So is there any other way to store edges(a pair of nodes)?

I'm a real fresh man in java field and I'm tring to learn this language better, I would appreciate for any suggestion!


Solution

  • In Java any List is an ordered collection of elements; but these elements can be objects of ANY class. So, the idea is that your element should be the unit of concern in your business logic. In your case, this is the pair of numbers. Given this, you could create a custom class called Edge for example that will be used as the elements of the List and have this Edge class store the respective pair of number. For example:

        static class Edge {
            private int first;
            private int second;
            
            public Edge(Scanner scanner) {
                this(scanner.nextInt(), scanner.nextInt());
            }
            
            public Edge(int first, int second) {
                this.first = first;
                this.second = second;
            }
    
            public int getFirst() {
                return first;
            }
    
            public int getSecond() {
                return second;
            }
    
            @Override
            public String toString() {
                return "Edge [first=" + first + ", second=" + second + "]";
            }
        }
    

    Then in your code change:

    LinkedList<Integer,Integer> adj = new LinkedList<Integer,Integer>();
    

    (which actually won't compile since List requires only a single generic type, not two) and replace it with:

    List<Edge> adj = new LinkedList<Edge>();
    

    making adj a List of Edge objects.

    • Additional Tips:

    You could also take advantage of Java 8 streams and enhanced NIO Apis and rewrite the entire transformation of the text file to a List<Edge> with the simple following method:

        public static List<Edge> readEdges(String filename) throws IOException {
            try (Stream<String> linesStream = Files.lines(Paths.get(filename))) {
                return linesStream
                        .map(line -> new Edge(new Scanner(line)))
                        .collect(Collectors.toList());
            }
        }
    

    Finally, the following is a full working demo of this approach, run it to get a feeling for it:

    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.List;
    import java.util.Scanner;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class EdgesReader {
    
        public static void main(String[] args) throws IOException {
            List<Edge> edges = readEdges("PATH/TO/MY/EDGES/TEXT/FILE");
            System.out.println(edges);
        }
    
        public static List<Edge> readEdges(String filename) throws IOException {
            try (Stream<String> linesStream = Files.lines(Paths.get(filename))) {
                return linesStream
                        .map(line -> new Edge(new Scanner(line)))
                        .collect(Collectors.toList());
            }
        }
        
        static class Edge {
            private int first;
            private int second;
            
            public Edge(Scanner scanner) {
                this(scanner.nextInt(), scanner.nextInt());
            }
            
            public Edge(int first, int second) {
                this.first = first;
                this.second = second;
            }
    
            public int getFirst() {
                return first;
            }
    
            public int getSecond() {
                return second;
            }
    
            @Override
            public String toString() {
                return "Edge [first=" + first + ", second=" + second + "]";
            }
        }
    }
    

    Complete code on GitHub

    Hope this helps.