Search code examples
javacomparatorpriority-queue

Issue with implementing custom Comparator for Priority Queue in Java



Please pardon my understanding towards priority Queue and Comparator in Java.
It seems ,I am able to implement basic comparator for Priority Queue based on some sort order.
But I am not able to come up with something for the below scenario :
1. Given a list of Files with name convention xx_yy_zz.dat .<br/>
2.xx,yy,zz can be from 00-50 <br/>
3.I need to process the files with xx=30 first,xx=35 second xx=40 third and then the rest.<br/>

Since I have limited knowledge with Priority Queue ,I tried to implement it which i was able to sort but only in asc or desc value of xx which was not the requirement.
My approach was

put the list of file names in priority Queue ,split the filename on regex "_" then compare the first index of split array using comparator based on it values but as expected i failed miserably since my requirement was something different

Please share some ideas/approach.

It seems sadly ,I am not able to come up with the a required comparator for my case .
Nevertheless thanking you in anticipation


Solution

  • You can use simple if statements inside the compare() method to check if one string starts with "30" and the other does not. Then you know that this string must come before the other one. You run the following if statements like this on the first part of the filenames:

    1. Are they the same?
    2. Is the left one 30?
    3. Is the right one 30?
    4. Is the left one 35?
    5. Is the right one 35?
    6. Is the left one 40?
    7. Is the right one 40?

    The comparator might look like this:

    public int compare(String a, String b) {
        String[] splitA = a.split("_");
        String[] splitB = b.split("_");
    
        if (splitA[0].equals(splitB[0])) {
            return 0;
        }
        if (splitA[0].equals("30")) {
            return -1;
        }
        if (splitB[0].equals("30")) {
            return 1;
        }
        if (splitA[0].equals("35")) {
            return -1;
        }
        if (splitB[0].equals("35")) {
            return 1;
        }
        if (splitA[0].equals("40")) {
            return -1;
        }
        if (splitB[0].equals("40")) {
            return 1;
        }
        return 0;
    }
    

    With the following test source code:

    System.out.println(Arrays.toString(data));
    Arrays.sort(data, new SpecialComparator());
    System.out.println(Arrays.toString(data));
    

    You might get an output like this (depending on the data array):

    [30_45_35.dat, 00_12_34.dat, 35_50_20.dat, 40_03_05.dat, 33_28_14.dat,
     30_16_31.dat, 20_29_23.dat, 24_41_29.dat, 30_49_18.dat, 40_12_13.dat]
    
    [30_45_35.dat, 30_16_31.dat, 30_49_18.dat, 35_50_20.dat, 40_03_05.dat,
     40_12_13.dat, 00_12_34.dat, 33_28_14.dat, 20_29_23.dat, 24_41_29.dat]
    

    (new lines added for clarity)

    As you see you have the 30s first, then the only 35 second, then the 40s third and after that all the remaining stuff. You might want to use compareTo() on the strings in case the compareTo method would return 0 to get better "sub sorting" of strings, which would be equal based on this basic sorting above.