Sorting string array by employee id number

Viewed 422

This is my code:

BufferedReader reader = new BufferedReader(new FileReader("Database.txt"));
ArrayList<String> str = new ArrayList<>();
String line = "";
while((line = reader.readLine()) != null){
    str.add(line);
}
reader.close();
Collections.sort(str);
FileWriter writer = new FileWriter("final.txt");
for(String s: str){
    writer.write(s);
    writer.write("\r\n");
}
writer.close();
FileWriter writers = new FileWriter("finals.txt");
for(String s: str){
    writers.write(s);
    writers.write("\r\n");
}
writers.close();   

Inputs:

DADDY,1,GOOD,BAD
BABY,3,GOOD, BAD

Output using my code:

BABY,3,GOOD,BAD
DADDY,1,GOOD,BAD

The array is sorted by names and not by the number. I want to sort it using the Number, 1 and 3.

Expected output:

DADDY,1,GOOD,BAD
BABY,3,GOOD, BAD

Is it possible to sort using Number??

3 Answers

You can sort it using a custom comparator that extracts the ID number, based on the assumption that it's between the first and second commas:

Comparator<String> comparator = Comparator.comparingInt(s -> {
  int firstComma = s.indexOf(',');
  int secondComma = s.indexOf(',', firstComma + 1);
  return Integer.parseInt(s.substring(firstComma + 1, secondComma));
});
str.sort(comparator);
  1. As it is an ArrayList of string, so default comparison does not work here.
  2. So you have to split the string and convert it to some other Object, where we can compare numerical values separately. So, create a Data object. And inside it, write your own compare logic by overriding the default compareTo method.
class Data implements Comparable{
    int val;// 1
    String name;// Daddy
    String status;// Good
    String mode; //bad
    Data(int val, String name, String status, String mode){
        this.val = val;
        this.name = name;
        this.status = status;
        this.mode = mode;
    }
    
    @Override
    public String toString() {
        return name+","+ val + ","+ status+","+ mode;
    }
    //Custom logic for sorting
    @Override
    public int compareTo(Object data) {
         int compareVal=((Data)data).val;
            
        return this.val-compareVal;

        /* For Descending order do like this */
        //return compareVal-this.val;
    }
}
  1. Your main code block will be,
    //ignore method name
    public void CustomDdWriter {
        //FileWriter writer;
        FileWriter writers = null;
        try {
            BufferedReader reader = new BufferedReader(new FileReader("Database.txt"));
            ArrayList<Data> dataList = new ArrayList<>();
            String line = "";
            while((line = reader.readLine()) != null){
                //split string and construct Data object and add it to dataList 
                dataList.add(parse(line));
            }
            reader.close();
            Collections.sort(dataList);
            
            writers = new FileWriter("finals.txt");
            for(Data d: dataList){
                writers.write(d.toString());
                writers.write("\r\n");
            }
            
            writers.close();
        }catch(Exception ex) {
            
            ex.printStackTrace();
        }finally {
            
        }

    }

    private Data parse(String line) {
        String[] sArray = line.split(",");
        return new Data(Integer.valueOf(sArray[1]), sArray[0],sArray[2], sArray[3]);
        
    }

Solution Explanation:

  • Need to read data from a file line by line.
    • BufferedReader handle this.
  • Need to sort those line(String) based on a inside numeric value.
    • We can not sort an array of string based on its inside numeric value. So, we need to create a custom Object, here Data Class.
    • We split a line by calling parse method. Parse method parse a string based on ,. And after parsing, we construct Data object using our custom constructor and return it.
    • Then we store this Data object into an ArrayList(dataList).
    • Finally we can call Collection.sort(dataList). But is it sort data in correct order? Inside Data class there are 4 members, for sorting which member will be chosen?
      • Inside Data class, there we @override compareTo method. There we declare, we want to sort data based on val member. So, Collection.sort(dataList) sort data based on desired numeric value.
  • Need to write in .txt file again.
    • To do this easily, inside Data class, we @override toString method. So during file write, it creates our desired string without any hassle.

For detailed codebase and explanation follow this github repo.

You can split each string into an array by commas and then sort those arrays by the second column using sorted method:

List<String> list = List.of(
        "DADDY,1,GOOD,BAD",
        "BABY,3,GOOD, BAD");

List<String> sorted = list.stream()
        // split into an array by commas,
        // and remove redundant spaces
        // Stream<String[]>
        .map(str -> str.split(",\\s*"))
        // sort by number
        .sorted(Comparator.comparing(arr -> arr[1]))
        // join back into one string
        // Stream<String>
        .map(arr -> String.join(",", arr))
        // collect strings into a list
        .collect(Collectors.toList());

// output
sorted.forEach(System.out::println);
DADDY,1,GOOD,BAD
BABY,3,GOOD,BAD
Related