Calling Comparator parameter in main method - java

I am implementing insertion sort method. Here is the requirement of my code.
The method insertionSort is a static method that returns nothing.
It has two parameters: a generic array and a Comparator (generic).
It sorts the generic array using the merge sort algorithms
My Question is: What do I use for Comparator parameter c when calling in main method?
Here is what I have so far, I have some unimplemented method (merge sort an isAnagaram) ignore those
public class Sorting
{
public static <T extends Comparable<T>> void insertionSort(T[] a, Comparator<T> c)
{
for (int i = 0; i < a.length; i++)
{
T key = a[i];
int j;
for (j = i - 1; j >= 0; j--)
{
if (c.compare(a[j], key) <= 0)
break;
a[j + 1] = a[j];
}
a[j + 1] = key;
}
}
public static void mergeSort()
{
//TODO
}
public static boolean isAnagram(String first, String second)
{
//TODO
return false;
}
public static void main(String[] args)
{
Integer a[] = { 99, 8, 19, 88, 62, 2, 1, 9, 19 };
// not sure how to pass parameter comparator
insertionSort(a, null );
for (int i = 0; i < a.length; i++)
{
System.out.print(a[i] + " ");
}
}
}
I looked around on stack overflow as well as googled a lot on a Comparator interface but I couldn't really find any method where you are required to pass Generic comparator as parameter. Can someone help me tell what I am not understanding or direct me to right direction.

Comparator is an interface, which can not be instantiated. You need to implement it. There are two methods to implement:
compare
equals
You need to implement them for Integer elements. Like this:
public class IntegerComparator implements Comparator {
public int compare(Integer a, Integer b) {
return a.intValue() - b.intValue();
}
public int equals(Object obj) {
return this.equals(obj);
}
}
and in your main you call it like this:
insertionSort(a, new IntegerComparator );
Explanation: Comparator is an interface, therefore it cannot be instantiated. You need to implement it. You have an array of Integer elements to sort, therefore you can implement an Integer Comparator. The compare method returns the subtraction of the int values. If a < b, then it is negative. If a == b, then it is 0. If a > b, then it is positive.
Read more here and here.

Related

Get a boolean answer from a custom Comparator

I have learned how to create my own Comparator, for example, create a simple one to compare based on absolute value
class absComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
return a * a - b * b;
}
}
And of course, this can be used for a customized sort:
List<Integer> list_1 = new ArrayList<>(Arrays.asList(-3, -2, -1, 0, 1, 2));
list_1.sort(new absComparator());
>>> [0, -1, 1, -2, 2, -3]
So this is all good, but what if I want to just compare two Integers based on this comparator to give a boolean value?
// Currently:
System.out.println(-2>1);
>>> false
So how do I get a true by comparing -2 and 1, using absComparator?
Call compare directly and check the result against 0 using the same relational operator. If you want to check -2 > 1, pass those two numbers in as parameters and check if the result is > 0.
Comparator<Integer> comparator = new absComparator();
System.out.println(comparator.compare(-2, 1) > 0);
IMO, method like isGreaterThan, isLessThan should be added to Comparator interface.
Since we don't have these in this moment, we can create our own interface extending Comparator, and add default method isGreaterThan, isLessThan, as follow:
public interface EnhancedComparator<T> extends Comparator<T> {
default boolean isGreaterThan(T target, T compareTo) {
return this.compare(target, compareTo) > 0;
}
default boolean isLessThan(T target, T compareTo) {
return this.compare(target, compareTo) < 0;
}
}
public class AbsoluteValueComparator implements EnhancedComparator<Integer> {
#Override
public int compare(Integer a, Integer b) {
a = Math.abs(a);
b = Math.abs(b);
return a.compareTo(b);
}
}
public class EnhancedComparatorTest {
public static void main(String[] args) {
EnhancedComparator<Integer> absoluteValueComparator = new AbsoluteValueComparator();
System.out.println("2 greater than 3 " + absoluteValueComparator.isGreaterThan(2, 3));
System.out.println("-3 greater than -2 " + absoluteValueComparator.isGreaterThan(-3, -2));
System.out.println("2 less than 3 " + absoluteValueComparator.isLessThan(2, 3));
System.out.println("-3 less than -2 " + absoluteValueComparator.isLessThan(-3, -2));
}
}
P.S.
a * a may overflow, you may refer to my example for more robust comparison.
References
The Java™ Tutorials Default Method
Java Doc Comparator
How does Java handle integer underflows and overflows and how would you check for it?
Java does not support operator overloading.
That being said, you can easily define your own static method for it:
private static final Comparator<Integer> ABS_CMP = new AbsComparator();
public static boolean gtAbs (int a, int b) {
return ABS_CMP.compare(a, b) > 0;
}
And then import it statically and use it operator-like:
import static your.UtilityClass.gteAbs;
[...]
int a = 5;
int b = -6;
if (gtAbs(a,b)) {
// do work
}
First, your problem is that you are not using your comparator.
class absComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
return a * a - b * b;
}
}
absComparator comp = new absComparator();
if (comp.compare(-2,1)) > 0) {
System.out.println(true);
}
But your comparator has a more fundamental problem. The following also
prints true. This is due to integer overflow when you subtract the products.
if (comp.compare(12345678, 123456789) > 0) {
System.out.println(true);
}
To correct the problem, write your comparator as follows:
class absComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
// eliminate the need for products by
// getting abs (Math.abs() also available);
int a1 = a >= 0 ? a : -a;
int b1 = b >= 0 ? b : -b;
// but you still should not subract as overflow can
// still happen for large values of a1 and b1
return a1 > b1 ? 1 : a1 < b1 ? -1 : 0;
// or return Integer.compare(a1,b1);
// or if (a1 > b1) {
// return 1;
// }
// if (a1 < b1) {
// return -1;
// }
// return 0;
}
}
Use an instance of your comparator:
absComparator comp = new absComparator();
int result = comp.compare(-2, 1);
if (result > 0) {
// -2 > 1 (according to your comparator)
}

Please explain sort() and compareTo()

I'm writing a code that compares twitter tweets.
Tweet constructor (Tweet class has implement Comparable) (declared inside Tweet.java):
public Treet(String author, String description, Date creationDate) {
mAuthor = author;
mDescription = description;
mCreationDate = creationDate;
}
Say I want to compare two tweets (declared inside Example.java):
Tweet tweetOne = new Tweet("Hello reddit", "josh", new Date(18909042L);
Tweet tweetTwo = new Tweet("Hello again reddit", "Susan", new Date (19419249L);
Then I made an array with these two tweets (declared inside Example.java)
Tweet[] tweets = {tweetOne, tweetTwo]
Then sort (declared inside Example.java)
Arrays.sort(tweets);
Here is my override compareTo() (declared inside Tweet.java)
public int compareTo(Object obj) {
Treet other = (Treet) obj;
if (equals(other)) {
return 0;
}
int dateCmp = mCreationDate.compareTo(other.mCreationDate);
if (dateCmp == 0) {
return mDescription.compareTo(other.mDescription);
}
return dateCmp;
}
A few things really making me bang my head on my desk:
1) how does sortTo() call the compareTo() method, if it does at all?
2) if no1 is true then why is it compareTo(Object obj) instead of compareTo(Tweet twt); seeing as tweets is an array of Tweet class? Presumably:
Array.sort(tweets) -----> compareTo(tweets) ?
3) if (equals(other)) what is equals to what here? Somebody told me that it is if(this.euqals(other)) but again what is this? Is it
tweetOne.equals(other) or tweetTwo.equals(other) or Tweet.equals(other)?
4) mDescription.compareTo(other.mDescription), again what is the mDescription here if
(other.mDescription) == ({tweetOne, tweetTwo}.mDescription)?
if I do this:
int val = mDescription.compareTo(other.mDescription)
What will val be?
I'm especially confused as to what is happening inside the compareTo() method as we want to compare tweetOne AGAINST tweetTwo but there are no evidence of that happening.
I hope someone can guide me through this, this is currently a huge road block for me atm.
Thank you very much in advance.
Java provides two similar mechanisms for comparing two instances for the purpose of ordering; Comparable.compareTo(T) and Comparator.compare(T, T). Both offer three-way comparison (from the linked Wikipedia entry)
Many object-oriented languages have a three-way comparison method, which performs a three-way comparison between the object and another given object. For example, in Java, any class that implements the Comparable interface has a compareTo method which returns a negative integer, zero, or a positive integer.
For an example as to how that can work in practice, consider a generic selectionSort like
static <T extends Comparable<? super T>> void selectionSort(T[] arr) {
int index = 0, i = 0, length = (arr != null) ? arr.length : 0, j;
for (; i < length - 1; index = ++i) {
for (j = i + 1; j < length; ++j) {
if (arr[j].compareTo(arr[index]) < 0) {
index = j; // <-- here we update the index when we find a smaller value
}
}
if (i != index) { // <-- if i == index then it is in the correct position
swap(arr, i, index);
}
}
}
Note that we could also do it with a Comparator;
static <T> void selectionSort(T[] arr, Comparator<T> comp) {
int index = 0, i = 0, length = (arr != null) ? arr.length : 0, j;
for (; i < length - 1; index = ++i) {
for (j = i + 1; j < length; ++j) {
if (comp.compare(arr[j], arr[index]) < 0) {
index = j;
}
}
if (i != index) {
swap(arr, i, index);
}
}
}
compareTo method checks for below things.
a negative integer if anObject < anotherObject
zero if anObject equals anotherObject
a positive integer if anObject > anotherObject
So in your case,
int dateCmp = mCreationDate.compareTo(other.mCreationDate);
if (dateCmp == 0) {
return mDescription.compareTo(other.mDescription);
}
return dateCmp;
}
Here is how it goes,
It first checks for dates, if dates are same, then compares the description.
Tweet will be compared based on description.
This article will definitely help http://www.thejavageek.com/2013/06/17/sorting-user-defined-objects-part-1/

Generic insertionSort using a Comparator object as a parameter?

If I'm given this method header:
/**
* This generic method sorts the input array using an insertion sort and the input Comparator object.
*/
public static <T> void insertionSort(T[] array , Comparator<? super T> comparatorObj){
// Implement method
}
For the Comparator<? super T> comparatorObj part in the parameter, am I suppose to be making a comparator object method that tells how it should be comparing when it's used in the insertionSort parameter?
You are supposed to pass in a Comparator object. Essentially, you just need to implement method
int compare(T obj1, T obj2)
Google some examples, e.g. http://www.tutorialspoint.com/java/java_using_comparator.htm
try this
public static <T>
void insertionSortGeneric(T[] a, Comparator<? super T> c) {
for (int i=0; i < a.length; i++) {
/* Insert a[i] into the sorted sublist */
T v = a[i];
int j;
for (j = i - 1; j >= 0; j--) {
if (c.compare(a[j], v) <= 0) break;
a[j + 1] = a[j];
}
a[j + 1] = v; }}

TreeSet in java in replacement of min hip for dijikstra algorithm

Since Java priority queue does not allow to update value of element in priority queue therefore I decided to use TreeSet in Java as an alternate of priority queue to implement Dijikstra shortest distance algorithm. Since I can find element in treeSet with O(log n) than I remove it and now I can insert new element in treeSet. TreeSet.first() always give me a lowest value in treeSet. But this idea is not working. I don't know why?
public class Dijikstra {
public static void dik(int n,int adj[][]) {
TreeSet<nod> p= new TreeSet(new Mycompare());
boolean visit[] = new boolean[n];
nod a[] = new nod[n];
for(int i = 0; i < n; i++) {
a[i] =new nod();
a[i].dis = Integer.MAX_VALUE;
a[i].id = i;
if(i == 0) {
a[i].dis = 0;
}
p.add(a[i]);
}
while(p.isEmpty() == false) {
nod temp = p.first();
p.remove(p.first());
visit[temp.id] = true;
for(int i = 0; i < n; i++) {
if(visit[i] == false && adj[temp.id][i] != 0) {
if(a[i].dis > temp.dis + adj[temp.id][i]) {
p.remove(a[i]);
a[i].dis = temp.dis + adj[temp.id][i];
p.add(a[i]);
}
}
}
}
for(int i = 0; i < n; i++) {
System.out.println(a[i].id+ " " + a[i].dis);
}
}
}
above is my Dijikstra class
my nod class is
class nod {
int dis;
int id;
}
my Mycompare class is
class Mycompare implements Comparator<nod> {
#Override
public int compare(nod t, nod t1) {
return t.dis - t1.dis;
}
}
From the javadoc of TreeSet:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal.
The javadoc of Set writes:
A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction.
That is, if the comparator returns 0, the element is considered a duplicate, and a set does not admit duplicates. Therefore, a TreeSet is not a priority queue.
after some research i am able to implement treeset which serve as a priority queue
instead of MyCompare class(which is useless) i have to implement compareTo method in class nod and declare treeset without any comparator
TreeSet set = new TreeSet()
class nod implements Comparable{
int dis;
int id;
#Override
public int compareTo(Object o) {
nod right = (nod)o;
if (dis < right.dis) return -1;
if (dis > right.dis) return 1;
if (id < right.id) return -1;
if (id > right.id) return 1;
return 0;
}
}

Java: QuickSort on LinkedList gives me exception

I'm studying for exam (Algorithms and data structures), and I'm trying to make quicksort work for LinkedList but it's giving me ListIndexOutOfBoundsException.
For homework a while ago, I used straightinsertion for sorting ArrayList and Vector, now I'd like to understand QuickSort (I do in theory) for LinkedList.
I'm not too familiar with linkedlist, but it shouldn't be too different from ArrayList?
public class Sort {
public static void quickSort(LinkedList<Oseba> a) {
sort(a, 0, a.size() - 1); // this is line 16
}
public static void sort(LinkedList<Oseba> a, int l, int r) {
int i = l;
int j = r;
Oseba x = a.get((l + r) / 2), w;
do {
while (a.get(i).mlajsi(x)) {
++i;
}
while (x.mlajsi(a.get(j))) { // this is line 31
--j;
}
if (i <= j) {
w = a.get(i);
a.set(i, a.get(j));
a.set(j, w);
++i;
--j;
}
} while (i <= j);
if (l < j) {
sort(a, l, j);
}
if (i < r) {
sort(a, i, r);
}
}
}
Oseba means 'a Person', it's a class I made for testing various methods (like sorting, comparing)
public class Oseba implements Comparable<Oseba> {
protected String priimekIme; //surnameName
protected int letoRojstva; //year of birth
protected Spol spol; //gender (enum)
public Oseba(String priimekIme, int letoRojstva, Spol spol) {
this.priimekIme = priimekIme;
this.letoRojstva = letoRojstva;
this.spol = spol;
}
#Override
public int compareTo(Oseba o) {
if (this.letoRojstva < o.letoRojstva) {
return -1;
} else if (this.letoRojstva > o.letoRojstva) {
return 1;
} else {
return this.priimekIme.compareTo(o.priimekIme);
}
}
public boolean mlajsi(Oseba o) { //younger
return (o.letoRojstva - this.letoRojstva <= 0);
}
#Override
public String toString() {
String s = priimekIme + ", " + spol.getKratko() + ", " + letoRojstva;
return s;
}
}
And this is an error I get:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: -1, Size: 6
at java.util.LinkedList.checkElementIndex(LinkedList.java:553)
at java.util.LinkedList.get(LinkedList.java:474)
at javaapplication1.Sort.sort(Sort.java:31)
at javaapplication1.Sort.quickSort(Sort.java:16)
at javaapplication1.JavaApplication1.main(JavaApplication1.java:55)
Java Result: 1
This quicksort method is supposed to work with Vector or ArrayList, I don't know why it wouldn't with LinkedList?
Thanks!
Well you don't check for boundaries during your loops.
while (a.get(i).mlajsi(x)) {
++i;
}
while (x.mlajsi(a.get(j))) { // this is line 31
--j;
}
should be
while (i <= r && a.get(i).mlajsi(x)) {
++i;
}
while (j >= l && x.mlajsi(a.get(j))) { // this is line 31
--j;
}
and
} while (i <= j);
strictly speaking, should also take account that i and j are inside the boundaries (but i think it is not neccessary).
It will solve the exception issue, but I didn't verify the correctness of the algorithm.
One of the big rules in Java (and OO in general) is "code to interfaces, not to implementations." Right now, you're coding to the LinkedList implementation of the List interface. The only way to guarantee that this code will work with any List (Vector, ArrayList, etc.) is to change your declarations. For instance:
public static void quickSort(LinkedList<Oseba> a) {
Should become
public static void quickSort(List<Oseba> a) {
And similarly with sort:
public static void sort(List<Oseba> a, int l, int r) {
Now, whenever you declare a person, it should look like this:
List<Oseba> a = LinkedList<Oseba>();
But in the place of LinkedList, you can substitute any other type of list.
This doesn't answer the question of why your code is failing -- I think UmNyobe's advice is good, though I didn't test it -- but it answers your lesser question as to why this code isn't acting like other list types. It's because you're coding to the implementation, where you should be using the interface.

Categories

Resources