Java Generic Comparator - java

public class arr<T>
{
class comp <T extends Comparable<T>> implements Comparator<T>
{
public int compare(T lObj,T rObj)
{
return lObj.compareTo(rObj);
}
}
ArrayList<T> list;
Comparator<T> comparator;
public arr()
{
list = new ArrayList<T>();
comparator = new comp();
}
public void add(T data)
{
list.add(data);
}
public int getLength()
{
return list.size();
}
public T get(int index)
{
return list.get(index);
}
public void sort()
{
list.sort(comparator);
}
}
Hello, I am trying to make the sort function work but have a problem.
In the arr constructor, if I write
comparator = new comp<T>();
it gives me an error saying
"type argument T#1 is not within bounds of type-variable T#2 comparator =
new comp<T>(); ^
where T#1,T#2 are type-variables:
T#1 extends Object declared in class arr
T#2 extends Comparable<T#2> declared in class arr.comp"
And if I take out the type and write like this
comparator = new comp;
then it does work but gives me a warning that says
warning: [rawtypes] found raw type: arr.comp
comparator = new comp();
I can see what it means by raw types. I am not specifying the type, but somehow it works and if I try to fix the warning by specifying the type then, it throws an error. Could you please help me figure it out? I know... I am a noob my code must be a pain in your eyes. I am playing with generic comparators and trying many things to get familiar. Thank you.

Your code is confusing you, because the T defined by comp is hiding the T defined by arr. For the explanation below, I'll call them Tcomp and Tarr.
Tcomp is required to extend Comparable, but Tarr isn't required to do so, which means that Tarr cannot be "mapped" to Tcomp.
To fix, change Tarr so it is also required to extend Comparable:
public class arr<T extends Comparable<T>>
On a side note:
You comp class is an inner class, but it doesn't use anything from the outer class, so it should be a static nested class:
static class comp<T extends Comparable<T>> implements Comparator<T>
Alternatively, leave comp as an inner class, and let it reuse the T from the outer class:
class arr<T extends Comparable<T>>
{
class comp implements Comparator<T>
But, since Java (8 or higher) comes with an implementation of Comparator for comparing Comparable objects, you should use it:
public class arr<T extends Comparable<T>>
{
ArrayList<T> list;
Comparator<T> comparator;
public arr()
{
list = new ArrayList<T>();
comparator = Comparator.naturalOrder();
}
// rest of code
}

Related

Do these two Java generic methods accept the same data types?

I'm new to Java and I'm trying to learn about generics. I tried to implement a simple version of binarySearch() method that is also found in the Collections class. I looked up the method signature and it's something like this:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
// definition
}
I was wondering if the method above still accepts the same data types if you were to change the method definition to this:
public static <T extends Comparable<? super T>> int binarySearch(List<T> list, T key) {
// definition
}
If not, what are the differences between the two? Thank you!
Consider these classes:
class A extends Comparable<A> { /* ... */ }
class B extends A { /* ... */ }
Now define a key and a list with these types:
A key = new B();
List<B> list = List.of(key);
You can invoke the first form with these arguments, but not the second.
For example:
static class NonComparable {
}
static class MyComparable implements Comparable<NonComparable> {
#Override
public int compareTo(NonComparable o) {
return 0; // irrelevant for the example
}
}
And then declare the parameters:
List<MyComparable> list = Arrays.asList(new MyComparable());
NonComparable nonComparable = new NonComparable();
binarySearch(list, nonComparable);
One of your method definitions allows an invocation, the other does not.

Using self-referential generic types in Java

Consider the following Java method:
<T extends List<T>> List<T> getMyList() {
return Collections.emptyList();
}
I can assign its output to a variable with a raw type, like so:
List x = getMyList();
List<List> y = getMyList();
But, I can't think of any way to assign its output to a fully parameterized type. In particular, I can't think of a non-raw, concrete type T that would satisfy List<T> z = getMyList();
Can we create such a T ?
If not, why not?
For context, I created this question while trying to understand how Enums are implemented in Java.
Here's an example of a concrete type that both works and starts to hint at a possible use-case (registration of some sort). The type consists acts like both an instance of some type, and as a container for all instances of that type.
public class WeirdEnum extends AbstractList<WeirdEnum> {
private static List<WeirdEnum> underlyingList = new ArrayList<>();
#Override
public WeirdEnum get(int index) { return underlyingList.get(index); }
#Override
public int size() { return underlyingList.size(); }
static <T extends List<T>> List<T> getAList() {
return Collections.emptyList();
}
public WeirdEnum() {
underlyingList.add(this); // Sufficient for our example but not a good idea due to concurrency concerns.
}
static List<WeirdEnum> foo = WeirdEnum.getAList();
}
Not sure if I fully understand your question, but here's an example:
class Example<T> implements List<Example<T>> {
...
}
...
List<Example<String>> list = getMyList();
Every enum in Java extends from the base-enum-class Enum<T extends Enum<T>>, where T is the actual type of the implementing enum.
When writing SomeClass<T extends SomeClass<T>> you can enforce that the type-parameter is always the implementing class itself.
Let's say you have this interface:
public interface MyInterface<T extends MyInterface<T>> {
T getSelf();
}
And this implementing class:
public class MyClass implements MyInterface<MyClass> {
public MyClass getSelf() {
return this;
}
}
In MyClass it is not possible to use any other type-parameter than MyClass itself.

Java: Specifying generic type restrictions in a subtype

I have a question regarding generic types in Java. Specifically, at present, I have some code similar to this:
public interface Foo {
public <T> void bar(T[] list)
}
public class FooImpl implements Foo{
#Override
public <T extends Comparable<? super T>> void bar(T[] list) {
...
}
}
The problem is, that the compiler now complaints, that I have not implemented the bar-method in my FooImpl class.
What I want is to put some extra restriction on the generic type, specifically that they should be comparable. But I don't want to put that restriction in my Foo interface, as all implementations does not need that restriction.
Is this possible, and what should I do to fix it?
Thanks a lot in advance!
EDIT 1: Fixed typos Class --> class and Interface --> interface. But the return types are still void, not T, which is irrelevant, I suppose. My actual return type is a boolean.
EDIT 2: The actual code, as requested:
public interface SortedCriteria {
public <E> boolean isSorted(E[] list);
}
public class AscendingCriteria implements SortedCriteria {
#Override
public <E extends Comparable<? super E>> boolean isSorted(E[] list) {
int length = list.length;
for (int i = 1; i < length; i++) {
if (list[i].compareTo(list[i-1]) < 0) return false;
}
return true;
}
}
What you want to do is rejected because it would completely break polymorphism. A caller having a Foo instance could have an instance of your subclass or an instance of any other subclass. And since the interface guarantees that the method can be called with any kind of array as argument, your subclass can't break this contract by limiting the kind of array it accepts (unless it does that at runtime, by checking the type of the array and by throwing an exception, of course).
This boils down to the Liskov substitution principle, which is the basis of polymorphism and OO.
But maybe what you actually want is to make Foo a generic type:
public interface Foo<T> {
public void bar(T[] list);
}
public class FooImpl<T extends Comparable<? super T>> implements Foo<T> {
#Override
public void bar(T[] list) {
...
}
}

Using generics in Comparable

I am trying to implement generics in Java using Comparable<T> interface.
public static <T> T[] sort(T[] a) {
//need to compare 2 elements of a
}
Let's say, I want to override the compareTo method for the above type T in the Comparable interface. I.e. I need to compare two elements of my type T, how will I do it? I don't know what my T type will be.
You need to set a type constraint on your method.
public static <T extends Comparable<? super T>> T[] sort (T[] a)
{
//need to compare 2 elements of a
}
This forces the type T to have the compareTo(T other) method. This means you can do the following in your method:
if (a[i].compareTo(a[j]) > 0) }
}
Try using <T extends Comparable<T>> and then compareTo
Old question but...
As jjnguy responded, you need to use:
public static <T extends Comparable<? super T>> T[] sort(T[] a) {
...
}
Consider the following:
public class A implements Comparable<A> {}
public class B extends A {}
The class B implicitly implements Comparable<A>, not Comparable<B>, hence your sort method could not be used on an array of B's if used Comparable<T> instead of Comparable<? super T>. To be more explicit:
public static <T extends Comparable<T>> T[] brokenSort(T[] a) {
...
}
would work just fine in the following case:
A[] data = new A[3];
...
data = brokenSort(A);
because in this case the type parameter T would be bound to A. The following would produce a compiler error:
B[] data = new B[3];
...
data = brokenSort(B);
because T cannot be bound to B since B does not implement Comparable<B>.

Signature of Collections.min/max method

In Java, the Collections class contains the following method:
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c)
Its signature is well-known for its advanced use of generics,
so much that it is mentioned in the Java in a Nutshell book
and in the official Sun Generics Tutorial.
However, I could not find a convincing answer to the following question:
Why is the formal parameter of type Collection<? extends T>, rather
than Collection<T>? What's the added benefit?
Type inference is a tricky topic that I'll admit that I don't know that much about. However, examine this example:
public class ScratchPad {
private static class A implements Comparable<A> {
public int compareTo(A o) { return 0; }
}
private static class B extends A {}
private static class C extends B {}
public static void main(String[] args)
{
Collection<C> coll = null;
B b = Scratchpad.<B>min(coll);
}
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c) {
return null;
}
//public static <T extends Object & Comparable<? super T>> T min(Collection<T> c) {
// return null;
//}
}
Consider that the first signature of min() allows the call to compile whereas the second does not. This isn't a very practical example, since one must ask why I would be explicitly typing the method to <B>, but perhaps there is an implicit inference where B would be the inferred type.
One benefit of the ? is that it prohibits additions of items to the Collection
I think it actually doesn't give you anything more for this method, however its a good habit to get into when T is part of the class and not just a static method.
They are including it here so it can become the new convention where every generic should be extended by ?
A class of T should follow PECS: What is PECS (Producer Extends Consumer Super)?
But a static method doesn't need to (at least the parameters, the return value should always)
This is to support a legacy signature of the method in Java 1.4 ( and before ).
Prior to Java 5 the signature for these methods was
public static Object min ( Collection c );
With multiple bounds the erasure rules make the first bound the raw type of the method, so without Object & the signature would be
public static Comparable min ( Collection c );
and legacy code would break.
This is taken from O'Reilly's Java Generics and Collections book, chapter 3.6
Building on the comments I put on Mark's answer, if you have something like
class Play {
class A implements Comparable<A> {
#Override
public int compareTo(A o) {
return 0;
}
}
class B extends A {
}
class C extends A {
}
public static <T extends Object & Comparable<? super T>> T min(
Collection<? extends T> c) {
Iterator<? extends T> i = c.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) < 0)
candidate = next;
}
return candidate;
}
public static List<? extends A> getMixedList() {
Play p = new Play();
ArrayList<A> c = new ArrayList<A>();
c.add(p.new C());
c.add(p.new B());
return c;
}
public static void main(String[] args) {
ArrayList<A> c = new ArrayList<A>();
Collection<? extends A> coll = getMixedList();
A a = Play.min(coll);
}
}
It's clearer that min returns an object of type A (the actual signature is <A> A Play.min(Collection<? extends A> c) ). If you leave min(Collection<T>) without the extends part then Play.min(coll) will have the following signature <? extends A> ? extends A Play.min(Collection<? extends A> c) which isn't as clear.

Categories

Resources