Collections.sort() error - java

I am trying to sort a list of type A named BinOrder in class B according to Class A's int r.
However i am receiving this error for the line Collections.sort(BinOrder);
The method sort(List<T>) in the type Collections is not applicable for the arguments (ArrayList<A>)
Class A:
public class A{
int s;
int r;
public A(int si, int ri) {
s=si;
r= ri;
}
}
Class B:
import java.util.ArrayList;
import java.util.Collections;
public class B implements Comparable<A> {
public Iterator<A> randomMethodName(int a) {
ArrayList<A> BinOrder = new ArrayList<A>();
A a = new A(1,3)
A a2 = new A(1,4)
BinOrder.add(a);
BinOrder.add(a2);
}
// sort array in increasing order of r
Collections.sort(BinOrder);
return BinOrder;
}
#Override
public int compareTo(A list) {
return null;
}
}

To be able to use the single-argument version of Collection.sort() on an ArrayList of A, A should implement the Comparable interface:
public class A implements Comparable<A> {
...
#Override
int compareTo(A rhs) {
...
}
}

Here's the signature of Collections.sort :
public static <T extends Comparable<? super T>> void sort(List<T> list)
A must implement Comparable for this method.
You try to pass BinOrder to this method, when BinOrder is of type ArrayList<A>, but since A does not implement Comparable<A>, it doesn't fit the signature of the method.
Either change A to implement Comparable, or use the sort method that accepts a Comparator :
public static <T> void sort(List<T> list, Comparator<? super T> c)

Related

Generics more restricted type for constructor

Let's say I will have multiple constructors, other can use T, but one constructor has to use Comparable
I tried to use
public <T extends Comparable<T>>TestT() // does not help
the code
import java.util.ArrayList;
public class TestT<T> {
private ArrayList<T> arr;
public TestT() {
arr = new ArrayList<>();
}
void push(T e){
arr.add(e);
}
}
How to make it so TestT constructor will allow only Comparable? Assuming I have other constructors which do not require Comparable
Your question doesn't make much sense since all constructor have the same name. Try using static methods instead:
public class TestT<T> {
private ArrayList<T> arr;
public static <X extends Comparable<X>> TestT<X> comparable() {
return new TestT<>();
}
private TestT() {
arr = new ArrayList<>();
}
void push(T e){
arr.add(e);
}
}
Please see if the below code answers to your requirements:
class TestT<T> {
private List<T> arr;
// Constructor that receives Comparable
protected <X extends Comparable<? super X>> TestT(X comparableIn1, X comparableIn2) {
/* Locate here your logic that transforms the input Comparable to List<T> */
// some foolish example implementation
if (comparableIn1.compareTo(comparableIn2) > 0) {
arr = new ArrayList<>();
}
else {
arr = new LinkedList<>();
}
}
// Another Constructor that receives a Collection of Comparable
protected <X extends Comparable<? super X>> TestT(Collection<X> comparableCollection) {
/* Locate here your logic that transforms the input Comparable Set to List<T> */
}
// Another Constructor that receives something else
protected TestT(List<T> listOfАrbitraries) {
arr = listOfАrbitraries;
}
void push(T e){
arr.add(e);
}
}
// Create different instances by the above Constructor receiving Comparable
TestT<Integer> arrayListOfIntegers = new TestT<>("1","0");
TestT<Object> linkedListOfObjects = new TestT<>("1","2");
Frankly, the notation <X extends Comparable<? super X>> can be simplified to just <X extends Comparable<X>>. In this case your Constructor argument's type will need to implement compareTo(X o) method, while in a manner I wrote above, the Comparable Interface can be also implemented by a method compareTo(<? super X> o) and the method's definition can be also in one of X's super types.

Are java comparators Type-aware?

I wanted a simple way to create a Comparator object based on any given Comparable class, so I coded the ComparatorCreator object, which I believed would look at the type of its generic and return the proper Comparator object that I could use to compare objects of that type. So I wrote the following code to test my idea. my belief would be that since the BackwardsInt class' compareto method is a reversed Comparator, it should be able to compare any two numbers in reverse order. But as it went through the statements, it completely ignored the reversal when it was comparing two ints, and even threw an error. I want to know why this is happening. The comparator I created seems to be aware of the type of the Number I'm passing in its arguments.
(I also got really into bounded wildcards a while back, so if that caused the problem, then oops).
import java.util.Comparator;
public class what {
public static void main(String[] ignoreme)
{
Comparator comp = new ComparatorCreator<BackwardsInt>().getComparator();
//comp should represent a Comparator<Number> which redirects to BackwardsInt.compareTo
int big=6;
int small=2;
BackwardsInt bbig=new BackwardsInt(6);
BackwardsInt bsmall=new BackwardsInt(2);
System.out.println(comp.compare(bbig, bsmall));//prints -1 good
System.out.println(comp.compare(bbig, small));//prints -1 good
System.out.println(comp.compare(big, small));//prints 1 why?
System.out.println(comp.compare(big, bsmall));//throws error?!?
}
private static class ComparatorCreator<T extends Comparable<? super T>>{
public Comparator<? extends T> getComparator()
{
return T::compareTo;
}
}
private static class BackwardsInt extends Number implements Comparable<Number>{
private int val;
public BackwardsInt(int v)
{
val=v;
}
#Override
public int compareTo(Number o) {
double d = o.doubleValue()-val;
if(d>0)
return 1;
if(d<0)
return -1;
return 0;
}
public int intValue() {
return val;
}
public long longValue() {
return val;
}
public float floatValue() {
return val;
}
public double doubleValue() {
return val;
}
}
}
Lets look at your ComponentCreator
private static class ComparatorCreator<T extends Comparable<? super T>>{
public Comparator<? extends T> getComparator()
{
return T::compareTo;
}
}
If have slightly changed it to make your mistake more clear
private static class ComparatorCreator<T extends Comparable<? super T>>{
public Comparator<? extends T> getComparator()
{
return (o1, o2) -> {
return o1.compareTo(o2);
};
}
}
The method reference you used is the same as the lambda I have but it makes the mistake more obvious. If we check your samples one by one we can see the following:
comp.compare(bbig, bsmall); // calls bbig.compareTo(bsmall)
comp.compare(bbig, small); // calls bbig.compareTo(small)
comp.compare(big, small); // calls big.compareTo(small)
comp.compare(big, bsmall); // calls big.compareTo(bsmal)
The output you received makes sense because big.compareTo() will call the compareTo() function of the Integer class.

Writing a generic method for sorting a set of comparables of any type

I have something like this:
public class A implements Comparable<A> {
...
#Override
public int compareTo(A obj) {
...
}
}
public class B implements Comparable<B> {
...
#Override
public int compareTo(B obj) {
...
}
}
I also have a bunch of HashSet collections that are slowly populated over the course of a program, e.g.:
private Collection<A> col = new HashSet<A>();
At the very end of the program I would like to convert them to sorted lists so they can be displayed sorted:
public class Utils {
public static <T> Collection<Comparable<T>> toSortedList(Collection<Comparable<T>> col) {
List<Comparable<T>> sorted = new ArrayList<Comparable<T>>(col);
Collections.sort(sorted);
return sorted;
}
}
Unfortunately I get the compile error:
The method sort(List<T>) in the type Collections is not applicable for the arguments (List<Comparable<T>>)
How do I go about modifying the above so HashSets of both Comparable<A> and Comparable<B> can be passed to this method? Thanks!
Use <T extends Comparable<? super T>> generic syntax:
public class Utils {
public static <T extends Comparable<? super T>> Collection<T> toSortedList(Collection<T> col) {
List<T> sorted = new ArrayList<T>(col);
Collections.sort(sorted);
return sorted;
}
}

conform equality constraints

I wrote some generic method. It works fine with first-level descendants. But it fails with objects of the second-level descendant.
package com.company;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static <T extends Comparable<T>> int f(List<T> list, T item) {
return 0;
}
static class A implements Comparable<A> {
#Override
public int compareTo(A o) {
return 0;
}
}
static class B extends A {
}
public static void main(String[] args) {
List<A> as = new ArrayList<A>();
List<B> bs = new ArrayList<B>();
A a = new A();
B b = new B();
f(as, a); // works
f(bs, b); // <-------- error
}
}
Compilation fails with:
Error:(29, 9) java: method f in class com.company.Main cannot be applied to
given types;
required: java.util.List<T>,T
found: java.util.List<com.company.Main.B>,com.company.Main.B
reason: inferred type does not conform to equality constraint(s)
inferred: com.company.Main.A
equality constraints(s): com.company.Main.A,com.company.Main.B
Why Java can not guess the equality variable types?
The type parameter T of your function f, has to implement Comparable<T> as per your definition <T extends Comparable<T>>. B does not implement Comparable<B>, but rather Comparable<A>. When you want to be able to call the function with B, the class should implement Comparable<B>, e.g. like so
static class B extends A implements Comparable<B> {
#Override
public int compareTo(B o) {
return super.compareTo(o);
}
}
Otherwise, you could change the type parameter of f to be able to have Ts which are subclasses of a Comparable class.
public static <T extends Comparable<? super T>> int f(List<T> list, T item) {
return 0;
}

Overload type parameter in Java class definition

Suppose I have a java class
public class Foo<ELEMENT, COMPARATOR extends Comparator<ELEMENT>> {
public Foo(ELEMENT e, COMPARATOR c) {...}
}
How can I reload the type parameter <ELEMENT> so that I can also have something like
public class Foo<ELEMENT extends Comparable> {
public Foo(ELEMENT e) {
this(e, new Comparator<ELEMENT>() {
public int compare(ELEMENT e1, ELEMENT e2) {
return e1.compareTo(e2);
}
})
}
}
You can't, basically. (TreeSet is an example of a class that would do it if it could.)
One thing you can do, on the other hand, is use static factory methods instead of public constructors. For example, you can write
public class Foo<E> {
public static <E> Foo<E> withComparator(E e, Comparator<? super E> comparator){
...
}
public static <E extends Comparable> Foo<E> withoutComparator(E e) {
...
}
}
This allows you to put different type constraints on different factory methods, e.g. adding a Comparable constraint on the overload that doesn't take a Comparator.

Categories