Best way of creating a Comparator that reverses order - java

This may seem like a dumb question, but I'd like to inquire about the best way to sort in reverse order a sortable structure (any kind, could be List) of a class MyClass that doesn't implement Comparable
First off, since MyClass doesn't implement Comparable and I want to sort it, I create a Comparator, something like this:
public class MyClassComparator implements Comparator<MyClass> {
#Override
public int compare(MyClass o1, MyClass o2) {
return (o1.getMyField()).compareTo(o2.getMyField());
}
}
This, of course, sorts MyClass objects according to the natural ordering of MyClass.MyField. But I want the reverse order.
I could of course just hardcode the reverse order in the compare(MyClass o1, MyClass o2) method. Something like
if (o1.getMyField()).compareTo(o2.getMyField()) > 0 return -1;
if (o1.getMyField()).compareTo(o2.getMyField()) < 0 return 1;
return 0;
Anoter alternative is leaving the code of MyClassComparator as I initially suggested, and using public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) from java.util.Collections to pass an instance of MyClassComparator and get a reverse comparator.
And a third alternative, that I think is wrong, could be sorting my LinkedList<MyClass> with the natural order Comparator and fetch the elements from last to first. LinkedList is a doubly linked list, so it should handle this perfectly. The problem is that I would always have to get a specific Iterator instead of just using a for each loop (minor) and, of course, that I initially wanted to sort ANY sortable structure, and I can't guarantee that it will be a doubly linked list or anything that handles well iterating through it in reverse order.
Considering that I'm quite certain (can't ever be 100% certain) that I won't be using the natural order of MyClass objects, just the reverse order, what would be the best way to obtain my reverse comparator?
Thank you.

Using a comparator would be the correct approach here in order to avoid the overhead of reversing an array. If the classes you are comparing implement Comparable you can just reverse the order of the comparison. obj2.compareTo(obj1). A way to visualize this is to think of the two objects as integers and compareTo as subtracting them.

Related

Data structure which can be sorted with iterator maintaining insertion order

This is a very generalized question, I'll try to be as clear as I can. let's say I have some collection of objects, for simplicity, make them integers. Now I want to make a class which represents these integers as some data structure. In this class I want to implement
a sort function, which sorts the collection according to some defined sorting logic
the iterable interface, where the Iterator traverses in insertion order
How could I make it so that, even if I add integers in unsorted order, e.g.
someCollection.add(1);
someCollection.add(3);
someCollection.add(2);
and then call
Collections.sort(someSortingLogic);
The iterator still traverses in insertion order, after the collection is sorted. Is there a particular data structure I could use for this purpose, or would it be a case of manually tracking which elements are inserted in which order, or something else I can't think of?
Many thanks!
Generally, to solve a problem like this, you maintain two indexes to the values. Perhaps one of those indexes contains the actual values, perhaps both indexes contain the actual values, or perhaps the actual values are stored elsewhere.
Then when you want to walk the sorted order, you use the sorted index to the values, and when you want the insertion order, you use the insert index to the values.
An index can be as simple as an array containing the values. Naturally, you can't store two different values into one spot in an array, so a simple solution is to wrap two arrays in an Object, such that calling the Object's sort() method sorts one array, while leaving the insertion order array untouched.
Fancier data structures leverage fancier techniques, but they all basically boil down to maintaining two orders, the insertion order AND the sort order.
public class SomeCollection {
public void add(int value) {
insertArray = expandIfNeeded(insertArray);
insertArray[insertIndex++] = value;
sortArray = expandIfNeeded(sortArray);
sortArray[sortIndex++] = value;
sort(sortArray);
}
...
}
I'm not sure you've shown us enough code to give you a good answer, but if you have a class that looks a bit like this:
public class Hand implements Iterator<Card>
{
private List<Card> cards = new ArrayList<>();
// Returns iterator for natural ordering of cards
#Override
public Iterator<Card> iterator()
{
return cards.iterator();
}
// Rest of code omitted
Then you can implement a sortedIterator(...) method like this:
// Returns iterator for sorted ordering by Comparator c
public Iterator<Card> sortedIterator(Comparator<? super Card> c)
{
return cards.stream().sorted(c).iterator();
}
If you show us some more code for what you have written, there may be better solutions.

What does Natural Order mean In this context in java?

I have a question which appeared in a past paper (I'm revising for my exams) and I came across this word natural order which appears to be a keywords since it was written in bold on the paper. I've looked online at Natural Order but I couldn't find anything that related it to arraylist's like my question asks.
Please note, I do not need help solving the actual question, I just wish to understand what natural order means.
Question:
Write a Java static method called atLeast which takes an ArrayList of objects which
have natural order, an object of the element type of the ArrayList, and an integer n. A
call to the method should return true if at least n elements of the ArrayList are greater
than the element type object according to natural order, otherwise it should return false.
This likely means the objects in the List implement Comparable:
This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.
The declaration would look something like this:
static <T extends Comparable<? super T>>
boolean atLeast(List<T> list, T key, int n) {
...
}
Natural order means the default ordering for a particular type of collection. It actually depends upon the type of collection you are using. eg. if its a string collection, it will be sorted in alphabetical order, for numbers it follows numerical order.
Refer here for better understanding about natural ordering.
You can have a look at here for detail.
For objects to have a natural order they must implement the interface java.lang.Comparable. In other words, the objects must be comparable to determine their order. Here is how the Comparable interface looks:
public interface Comparable<T> {
int compareTo(T o);
}

Comparable as argument in Java

I have a class PriorityList with the signature
Tree<Key extends Comparable<Key>, Value>(which is given, I can't modify). The elements Tree are inserted in some order, given the key (i.e. it considers the key's compareTo method).
Let's say I have Tree<Integer, Integer>. The default compareTo of integer considers ascending order. I would like to be able to somehow have Tree insert the elements in descending order, if I wanted to. I know I could probably write another class MyInteger which implements Comparable and has a compareTo on its own.
But is there another way? What I would really like is to be able to somehow tell the Tree how to order the values.
Second question: If I were able to modify Tree, how would one pass a comparator as argument? (keeping generic types-syntax in mind).
You've named the two ways to do it: pass in a comparator or have key be comparable. If the class doesn't let you pass in your own comparator, then you're stuck monkeying with the keys or creating your own subclass with the Comparable interface
The alternative code would look something like this.
public class Tree<K,V>{
public Tree( Comparator<K> cmp ) {...}
}
You wouldn't need to create a new class for reverse. you can use Collections.reverseOrder() to obtain a Comparator in reverse of a given one.
As for the second question, you will simply add a setter to your tree. Something like: setComparator(Comparator<Key> c) and then use that comparator for all the comparisons needed in your Tree.

Java String Array

i have two array
String a[]={"11","02","43","24","05","86","37","28","29","10"};
String b[]={"a","c","f","q","w","x","z","x","s","r"};
i want to sort array a[] in ascending order
and the result may like
String a[]={"02","05","10","11","24","28","29","37","43","86"};
String b[]={"c","w","r","a","q","x","s","z","f","x"};
how can i get result like above using java?
any sorting method available in java?
The easiest way would be to link the 2 pieces of data together in some way instead of having them in separate arrays. Many people have suggested a Map which would work great. Depending on exactly what you are trying to do, I would also consider a new class with 2 variables that implement Comparable. Comparable defines the natural ordering of a class when it is in a Collection (in this instance an array) if Collections.sort is not given a different Comparator to use. It would look something like this:
public class Data implements Comparable{
private String stringOne;
private String stringTwo;
#Override
public int compareTo(Object obj) {
stringOne.compareTo((String)obj);
}
Somewhere else call:
Collections.sort(locationOfDataCollection);
You could then create one Collection of Data and access the other String with a getter method. This implementation also would make it simple in future (see Strategy Design) if in some instances the natural order needed to be overridden with a new Comparator (e.g. sort by stringTwo).
Since you have 2 related sets of data, I would either link these via a Pair<String,String> type object and then into a List<Pair>, or put them into a Map<String,String>.
Perhaps the first solution is more intuitive e.g.
public class Pair implements Comparable<Pair> {
public String first;
public String second;
// equals/hashcode etc.
}
Once they're in a standard Java collection, numerous solutions exist for sorting these. e.g. in the above Pair I've implemented the Comparable<T> interface which the Collections sorting mechanisms will make use of.
There is no methods for directly doing this in Java. You have two options.
1) Define a Map<String, String>, put all the pairs in it (like ("11", "a")). Sort first array (or the keys of the map) and retrieve the elements of the map in that order.
2) Create an object that holds each par, create a List with it, and sort comparing only by the number (implement Comparable or create a Comparator).
One issue you'll need to be aware of is that Strings don't sort according to the same rules as integers. You are likely to be surprised by what you get if you leave the array by which you sort as String.

Sorting generics in Java

I have to implement a generic AVL tree as homework. It's defined as follows:
public class AVL<Key,Elem>;
The problem is that I assume that at some point, I'll have to compare keys to decide in which side of a node I allocate an element. For the purpose of this homework, Integers will be used as Keys.
Since no other restriction or information about that is given, I first thought of just asuming that Key will always be an Integer. However, that makes the generic "Key" superfluous, and I don't think that's what the teachers expect. So, I think that the best solution involves forcing that whatever that is passed as Key implements a Comparator, or something like that (I've really never worked with Comparator, just guessing), and then using that comparator to compare the Keys instead of using the ==,<,> and != operators. However, I have no idea on how to do it. Any hints?
Thanks in advance.
Try public class AVL<Key extends Comparable<Key>,Elem>; and use the compareTo() method which is required by the Comparable<T> interface and which is implemented by Integer.
The SortedMap and SortedSet implementations in the standard Java API either use a Comparator<Key> and call its compare(k1, k2) method, or assume the keys implement Comparable<Key>, and call k1.compareTo(k2). Most offer both, depending on which constructor is used. (EnumMap/EnumSet don't, as they support only the build-in ordering of the enum values by declaration order.)
The Comparable approach mandates that the keys are always sorted in the same way, and would be used for keys which have a canonical ordering (like integers), where you want to use this ordering.
The Comparator approach is more flexible, since you can use the same key objects for different maps where they are differently ordered, and you can use it for keys over which you have no control, or who don't have a canonical ordering (like List, trees/graphs, etc. You can also use it to sort strings keys by other criteria than the pure unicode value (e.g. Locale-based), using a Collator (this is a class implementing Comparator).
Both require a total order on your keys, but I suppose this is necessary for your AVL tree, too.
Here is a Comparator implementation which works on any comparable objects, so you could use it (maybe internally) as an adapter for the Comparable variant.
public static <X extends Comparable<X>> Comparator<X> makeComparator() {
return new Comparator<X>() {
public int compare(X left, X right) {
return left.compareTo(right);
}
};
}

Categories