-1

I have a list to be sorted but it cannot be done if values are represented as strings. Example:

to sort: OB123, OB1212, Maintenance, Daily check, OB123
desired result: Daily check, Maintenance, OB123, OB123, OB1212
if values are strings result is: Daily check, Maintenance, OB1212, OB123,OB123

Therefore I need to use comparator to first sort aircraft numbers such OB123 by their carrier(OB), than by their number (123) and sometimes suffix (""). And after that I would like to compare the whole name with all the rest values as "daily check" etc. So far I can sort only flight Ids:

@Override
public int compareTo(FlightNumberDisplay toCompare) {

int result = _carrier.compareTo(toCompare.getCarrier());
if (result == 0) {
  result = _number.compareTo(toCompare.getNumber());
  if (result == 0) {
    result = _suffix.compareTo(toCompare.getSuffix());
  }
}

return result;
}

So since "Daily check" has also carrier+number+suffix representation it is sorted according to it. The question is how to sort them according to their names.

Marty
  • 117
  • 9
  • If you're using Java 8, you can use [Comparator chaining](http://www.java8examples.com/how-to-chain-comparators-in-java-8/) (look for "thenComparing"). – Andy Turner Aug 23 '16 at 08:42
  • nope, I don't use it – Marty Aug 23 '16 at 08:45
  • One option is to write a string comparator that takes the flight numbers into account: If two strings both begin with letters followed by digits and the letters are the same, convert the digits into integers and compare them. – Ole V.V. Aug 23 '16 at 09:06

2 Answers2

1

Well, you can make a comparison checking for numbers in the strings:

FlightComparator.java

public class FlightComparator implements Comparator<String> {
    public int compare(String arg0, String arg1) {
        // both have numbers, compare them
        if (containsNumber(arg0) && containsNumber(arg0)) {
            Integer i1, i2; 
            try {
                i1 = getNumber(arg0);
            } catch (NumberFormatException ex) {
                return 1;
            }
            
            try {
                i2 = getNumber(arg1);
            } catch (NumberFormatException ex) {
                return -1;
            }
            
            return i1.compareTo(i2); 
        } else {
            // no numbers
            return arg0.compareTo(arg1);
        }
    }
    
    private boolean containsNumber(String string) {
        return string.matches(".*\\d+.*");
    }  
    
    private Integer getNumber(String string) throws NumberFormatException {
        return Integer.parseInt(string.replaceAll("\\D+",""));
    }
}

TEST IT

public static void main(String[] args) {
    String[] ss = {"OB123", "OB1212", "Maintenance", "Daily check", "OB123"};
    Collections.sort(Arrays.asList(ss), new FlightComparator());
    list(ss);
}

private static void list(String[] ss) {
    for (String s : ss) {
        System.out.println(s);
    }
}

OUTPUT

Daily check
Maintenance
OB123
OB123
OB1212

DISCLAIMER

Now, while this data seems correct for what you ask, is not a real answer to your problem. Also if flight letters are different ie, OM1212, OR1212, this will only compare the numbers, so to complete solve your problem now, you can choose between

  • use this Comparator and compare data as shown (not using attributes)
  • adapt this Comparator<String> to Comparator<Flight> (best option)

CREDITS

Community
  • 1
  • 1
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • 1
    Nice. As you said in the disclaimer, making it a `Compartor` is probably even better, but we don’t have enough information for providing that. I suppose you should still sort by carrier before sorting by number. In `&& containsNumber(arg0)` it should probably be `arg1`. I’m sure the OP can fix such details. – Ole V.V. Aug 23 '16 at 09:28
  • I don’t know whether its nitpicking or helpful (or both): Last time I flew, the carrier code was “4U”. It may be that you should take digits in carrier into account too. It may also be that your code also sorts those correctly, I would at least want to test. – Ole V.V. Aug 23 '16 at 09:39
  • Note that there is an inconsistency: if both `getNumber` invocations would throw a `NumberFormatException`, a `1` is returned, regardless of the order, which violates the comparator’s symmetry contract. But since these exceptions shouldn’t happen anyway, the fix is easy: don’t catch the `NumberFormatException` at all. – Holger Sep 06 '16 at 12:00
0

You can extract the carrier information in another List, there you can parse it by Integer using parseInt() and then sort it.

Later you can merge both lists.

svarog
  • 9,477
  • 4
  • 61
  • 77
Chips
  • 65
  • 1
  • 9
  • While this might be a valuable hint to solve the problem, an answer really needs to demonstrate the solution. Please [edit] to provide example code to show what you mean. Alternatively, consider writing this as a comment instead. – Toby Speight Aug 23 '16 at 13:23