1

Let's say, we have a relay race. Each member of the team runs their own path, passing the stick to the next member of the team. I have class, that describes track number (each team has own track number) and two names. The first name is stick's owner for part of track N and the second name is stick's owner for next part of the track (N+1).

class StickTransfer {
    int trackId;
    String stickFrom;
    String stickTo;
}

My task is to sort all the StickTransfer's objects by 1) tracked 2) In order of stick's travel.

E.g. Let's say there is a team on track 1 with Alex -> John -> Smith -> Adam.

list.add(new StickTransfer(1, "John", "Smith");
list.add(new StickTransfer(1, "Alex", "John");
list.add(new StickTransfer(1, "Smith", "Adam");

order(list)
// After that I want to get:
// Alex - John - first entry
// John - Smith - second entry
// Smith - Adam - third entry

So, at first I deсided to use Java's sorting with such kind of comparator:

Comparator.comparing(StickTransfer::getTrackId)
            .thenComparing((o1, o2) -> {
                if (o1.getStickFrom().equals(o2.getStickTo())) {
                    return 1;
                }
                if (o1.getStickTo().equals(o2.getStickFrom())) {
                    return -1;
                }
                return 0;
            });

But I got a problem, that with this comparator some of the entries are still unsorted. I think that's because it's not really a good comparator.

Now I have some questions:

1) Is it possible to write a right comparator for standard java sort method?

2) If not, is there a way to resolve this problem with some of Java standard methods?

3) Is there a name for such algorithmic problem?


Example of wrong sorting: Right order: X -> Y -> A -> B -> C -> D -> E

    StickTransfer stickTransferArr[] = {
            new StickTransfer(1, "A", "B"),
            new StickTransfer(1, "C", "D"),
            new StickTransfer(1, "B", "C"),
            new StickTransfer(1, "X", "Y"),
            new StickTransfer(1, "Y", "A"),
            new StickTransfer(1, "D", "E")
    };

    Arrays.sort(stickTransferArr, cmp);

Result:

[{track=1, [A - > B]}, {track=1, [B - > C]}, {track=1, [C - > D]}, {track=1, [X - > Y]}, {track=1, [Y - > A]}, {track=1, [D - > E]}]
Feedforward
  • 4,521
  • 4
  • 22
  • 34
  • 1
    Can you please show us an example of "some of the entries are still unsorted"? And you can simplify `thenComparing` by using `.thenComparing((o1, o2) -> o1.getStickFrom().compareTo(o2.getStickTo()))` – Anton Balaniuc Sep 14 '18 at 10:59

1 Answers1

3

3) Is there a name for such algorithmic problem?

The problem you have is called topological sorting.

1) Is it possible to write a right comparator for standard java sort method?

No. If you have more than two elements, there will be elements that are not directy comparable. In your example: StickTransfer(1, "Alex", "John") and StickTransfer(1, "Smith", "Adam") - which one of those comes before? It's not possible to know without looking at the other elements.

2) If not, is there a way to resolve this problem with some of Java standard methods?

Yes, there are plenty of implementations, for example: Sample Directed Graph and Topological Sort Code

Fundamentally, you can use depth-first search on the graph to sort it topologically.

kfx
  • 8,136
  • 3
  • 28
  • 52