I came across the following code. Here, how are we initializing a comparator in the constructor of priority queue?
I know comparator is an interface in Java and should be implemented in another class.
Ideally, we should implement comparator in a class and use its initialization in the PriorityQueue constructor.
But the following code works. How?
PriorityQueue<ArrayList<Integer>> heap = new PriorityQueue<ArrayList<Integer>>(10, new Comparator<ArrayList<Integer>>(){
public int compare(ArrayList<Integer> list1, ArrayList<Integer> list2) {
return list1.get(2) - list2.get(2);
}
well in reference code snap, priority queue object has been created using constructor which takes two object as arguments viz type int and of type Comparator.
In reference code snap, Comparator type object has been created as anonymous inner class and passed to PriorityQueue constructor as second object.
for better understanding you can break that statement in below two statement.
1st will create comparator object, 2nd will pass that object to blocking queue.
Comparator> comparator = new Comparator>(){
public int compare(ArrayList list1, ArrayList list2) {
return list1.get(2) - list2.get(2);
}
};
PriorityQueue> heap = new PriorityQueue>(10, comparator );
Related
In my taks I need to sort names with lambda. Class lambdaComparator extends class Car.
I make class LambdaComparator like this:
public class LambdaComparator extends Car
public LambdaComparator(String name) {super(name);}
In this class I need to sort objects of type Car.
In main class I have list of objects and with function I need to sort it.
In class LambdaComparator I have this:
Collections.sort(list, new Comparator<Car>() {
public int compare(Car x, Car y) {
return x.getName().compareTo(y.getName()));
}
});
How should I call function in main to get this sorted, should I make function of type void in class to somehow call it.
Edit: lambda expression
class LambdaSort<T extends Car>
private List<T> listOfCars;
public LambdaComparator(){
this.listOfCars = new ArrayList<T>();
}
public void sortCars(T cars)
listOfCars.sort((Car o1, Car o2)->o1.getName().compareTo(o2.getName());
In main function I add objects of type car to that list.
A lambda comparator would be something like this.
Comparator<Car> comp = (c1, c2)-> c1.getName().compareTo(c2.getName());
In the above example, the Comparator is comparing on a specific field of the Car class, name. Since name probably returns a string, one can use compareTo since the String class implements the Comparable (not Comparator) interface for comparing Strings.
But the lambda could be specified much more easily using one of the methods in the Comparator interface. The comparing method may take a lambda or a method reference (shown below).
Comparator<Car> comp = Comparator.comparing(Car::getName);
Then when it is passed to the sort method, the sort method will apply it to the objects under sort as comp.compare(obj1, obj2) (although it may not be called comp in the method that uses it)
For more information, check out The Java Tutorials
Take a look at what lambda is here.
If you have a list in your main class, it's as simple as just sorting it. You probably don't even need the class LambdaComparator.
List<Car> list = new ArrayList<>();
Collections.sort(list, (a, b) -> a.getName().compareTo(b.getName()));
I have a question regarding the Comparator interface. Below my class implements the interface to sort strings by length instead of by the default sort which sorts by character value.
After overriding the default compare, I used Arrays.sort() to sort my string array. Even though I have overridden the default method, if I use Arrays.sort, it calls the default compare instead of my overridden method. Is this because I am explicitly calling the super class method?
The other question is initializing the interface itself. I know you cannot initialize an interface and instead initialize a class object (that implements said interface) to reference the methods available to the interface. In this case, when I initialize a comparator, Arrays.sort(strArr, new Ideone()); the sort works correctly. How does the method know that I am passing it a comparator? I only initialized a class object and didn't call the compare(ob1, ob2) method explicitly.
Even if I do Comparator x = new Ideone();, how is the class object reduced to a comparator object? Any explanation on this would be helpful.
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone implements Comparator
{
static String ThirdGreatest(String[] strArr)
{
Arrays.sort(strArr);
//Arrays.sort(strArr, new Ideone());
for(String x: strArr)
{
System.out.println(x);
}
return strArr[strArr.length-3];
}
#Override
public int compare(Object s1, Object s2)
{
return (s1.toString().length() - s2.toString().length());
}
public static void main (String[] args) throws java.lang.Exception
{
String[] myarr = {"coder","byte","code", "asfasfasfasf"};
System.out.println(ThirdGreatest(myarr));
}
}
Even though I have overridden the default method, if I use Arrays.sort, it calls the default compare instead of my overridden method. Is this because I am explicitly calling the super class method?
No, it's because in the example you've given, you don't pass in the comparator - so the sort method has no way of know that you're trying to use a custom comparison.
In this case, when I initialize a comparator, Arrays.sort(strArr, new Ideone()); the sort works correctly. How does the method know that I am passing it a comparator?
Because you're calling the overload that accepts a comparator. There is only one overload with two parameters:
public static <T> void sort(T[] a, Comparator<? super T> c)
Now admittedly it would be better if you implemented Comparator<String> instead of the raw Comparator type, but it's still valid.
I only initialized a class object and didn't call the compare(ob1, ob2) method explicitly.
Indeed - you don't have to call compare. That's the job of the sort method. You pass the comparator in so that it can call compare.
I think the issue here is that while you've created a comparator for use in Arrays.sort, you haven't actually told Arrays.sort to use it. By default, if you just say
Arrays.sort(strArr);
then the strings will be sorted using the default comparator. To tell the sorting algorithm to use your custom comparator, you need to pass it as a second argument to the method:
Arrays.sort(strArr, new Ideone());
Try seeing if that fixes things. As a fun test, put a println statement in your comparison function to see if you can watch it getting called.
That said, it's pretty unusual to implement the comparator this way. A more common route would be to do something like this:
Arrays.sort(strArr, new Comparator<String>() {
public int compare(Object s1, Object s2) {
return (s1.toString().length() - s2.toString().length());
}
});
Now, you don't need to implement compare on the Ideone class, which makes clearer that (1) it's not going to get called automatically, and (2) you only need it for this one sorting step.
Arrays.sort(strArr)
This sorts an array of string objects using the java comparator. You haven't told your sort function to use the compare function you created. There needs to be a reference to your Ideone class.
Comparator x = new Ideone();
Because Ideone() implements Comparator, it must implement all the methods within the Comparator interface. The variable x would use the compare method of the Ideone class as it is overridden. However, if you try to use a method from the Ideone class that isn't in the Comparator class then you'll throw an exception.
I am creating a class that, at present, stores lists of various types in an internal object called genericTable. Each list (composed of either Double, or Long) are all held in an object which is an instance of class GenericList.
Question: Why doesn't the method addVector work?
The error under the red underline says the constructor Test<V>.GenericList<V>(List<List<V>>) is undefined.
If I was working in a main method (but had the same GenericList class) and created genericTable within the main method (using List<GenericList<?>> Table = new ArrayList<GenericList<?>>();) and did genericTable.add(new GenericList<Long>(Arrays.asList(genericVector))); (where genericVector in this case is a List<Long>), it works perfectly.
public class Test<V> {
private final List<GenericList<?>> genericTable = new ArrayList<GenericList<?>>();
public void addVector(List<V> genericVector) {
genericTable.add(new GenericList<V>(Arrays.asList(genericVector)));
}
private class GenericList<K> {
private final List<K> listGeneric;
public GenericList(List<K> input) {
listGeneric = input;
}
}
}
You're unnecessarily using Arrays.asList(), when you already have a list. Consequently you get a list of lists, which is not what the constructr accepts.
See this from the javadocs:
This method also provides a convenient way to create a fixed-size list
initialized to contain several elements:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
So in your case you're getting a list of lists, instead of a list of strings.
I've added this bit from the comments, for clarity:
The method signature for asList() is like this:-
public static <T> List<T> asList(T... a)
So because T... a is a vararg, when you pass in "Larry", "Moe", "Curly", the compiled method actually receives an array of ["Larry", "Moe", "Curly"], and returns them as a List.
So because you passed in a List, rather than an array, the method takes the vararg array like this: [genericVector], and returns that array as a list, and you constructor breaks.
I know that Collections.sort(myArrayList) can sort an arraylist alphabetically when they are strings, but what about when they are something more complex such as a data object containing two or more variables including a String. Is there a way to sort them then?
If there isn't a way with Collections then I can imagine making a for loop or standard sorting algorithm to look at the strings variable of each object and move the object's index in the array.
But I was wondering mainly if I overlooked something about the Collections methods
Use the function taking as second parameter a Comparator.
Il allows you to pass an instance of Comparator to sort according to your needs. Note that the javadoc of Comparator contains guidelines regarding the building of comparators.
You may define the comparator as an anonymous class if it's only locally used. Here's an example where I sort objects regarding to one of their fields which is a String :
Collections.sort(groupResults, new Comparator<ProductSearchResult>() {
public int compare(ProductSearchResult result1, ProductSearchResult result2) {
return result1.product.getRsId().compareTo(result2.product.getRsId());
}
});
Alternatively, you might also make your class implement the Comparable interface but this makes sense only if you can define a natural (obvious) order.
I would create an inner class implementing the Comparator interface:
public class Car {
public double horsePower;
class CarHorsePowerComparator implements Comparator<Car> {
#Override
public int compare(Car car1, Car car2) {
return Integer.valueOf(car.horsePower).compareTo(Integer.valueOf(car2.horsePower)) }
}
}
Now when you want to sort your Car list by horsePower:
List<Car> list = new ArrayList<Car>(myCars); //your Car list
Collections.sort(list, new CarHorsePowerComparator());
I'm trying to sort a Vector in java but my Vector is not a vector of int, it is a vector of objects
the object is:
public MyObject() {
numObj = 0;
price = new Price();
pax = new Pax();
}
so I have a Vector of MyObject and I want to order it by numObject, how do i do it, I'm new in java?
Thank you so much for all your help.
I assume you are using Collections.sort(..). You have two options:
make your class implement Comparable
when sorting, create a custom Comparator
An example for implementing Comparable would be:
public class MyObject implements Comparable<MyObject> {
// ..... other fields and methods
public int compareTo(MyObject other) {
return numObj - other.getNumObj();
}
}
This will mean the items are sorted in ascending order. If you want other, custom sorting, you can create a Comparator that defines the custom comparison and pass it as an argument to Collections.sort(..);
To sort a vector of object, first the class MyObject must implement Comparable and implement method compareTo(Object), then use Collections.sort(Vector)
class MyObject implements Comparable<MyObject> {
public int compareTo(MyObject a) {
//return either 1, 0, or -1
//that you compare between this object and object a
``}
}
//and in your logic write this line
Collections.sort(myVector);
check the JavaDoc of Vector
Implementing Comparable will work fine. However, it should be done with caution in order to prevent future bugs. The implementations above are great for sorting, but if you later decide to put your MyObject instances into a SortedSet (such as TreeSet), you will have an unexpected behavior. Items which are not identical will collide with each other if they have the same value of the numObject data member. This happens because sorted sets use the Comparable implementation (by default) in order to determine equality.
See http://eyalsch.wordpress.com/2009/11/23/comparators/ for details.