Search code examples
javalistsortingguava

Sort list based on comparator defined on another list using Guava Ordering


I've two lists of same size : List<A>listA, List<B>listB that are completely independent of each other.

I'd like to sort listA based on how the elements move in listB.

Assume there's an imaginary connection b/w the two lists.

Eg:

listA = [a,b,c,d,e]
         | | | | |
listB = [j,g,h,k,i]

If the listB's comparator sorts it lexicographically, listA should be b,c,e,a,d

listA = [b,c,e,a,d]
         | | | | |
listB = [g,h,i,j,k]

I don't want to create a class that encapsulates both A & B.

I've come across Ordering.explicit() but not able to figure it out.

  private static  class ComparatorB implements Comparator<B> {
    @Override
    public int compare(B left, B right) {
      
    }
        
    }

Ordering<B> ordering = Ordering.from(new ComparatorB());

I'm not able to figure out what to pass to sort method. listA.sort(????)


Solution

  • How about this?

    listB.sort(new ComparatorB());
    listA.sort(Ordering.explicit(listB)); // or possibly a mapped version
    

    Or if you want to change a B-comparator into an A-comparator, you could do

    listA.sort(Ordering.from(new ComparatorB()).onResultOf(a -> mapAtoB(a)))
    

    Update after question update
    You could do it like this:

    Streams.zip(listA.stream(), listB.stream(), Pair::new)
                    .sorted(Ordering.from(new ComparatorB()).onResultOf(Pair::getFirst))
                    .map(Pair::getSecond)
                    .collect(Collectors.toList());
    

    I'm not sure if you'd count that Pair as "creating a class that encapsulates both A & B", but it's not clear why you don't want that anyway. This is probably your best bet.