Сравнение общих c типов (расширяет и реализует в контексте LinkedList с использованием частного класса узлов) - PullRequest
0 голосов
/ 01 августа 2020

У меня есть стандартный класс LinkedList с узлами, которые имеют поля данных типа generi c, и я пытаюсь сравнить их, но не знаю, go как мне это сделать.

Мой класс узла

private static class Node<E> 
{
    E data;
    Node<E> prev;
    Node<E> next;
}

В основном, я пытаюсь сделать

if(nodeA.data > newData)
     //do something

Должен ли я делать что-то вроде

public class MyLinkedList<E extends Comparable <E>>

или public class MyLinkedList<E> implements Comparable <E>

И для обоих способов реализовать собственный метод compareTo? Я пробовал это, но compareTo обычно выглядит как

public int compareTo(E data)
{
    if(this > data)
        return 1;
    //add others
}

И здесь 'this' будет относиться к моему классу LinkedList, а не к общему c типу E.

Спасибо ты

Ответы [ 3 ]

1 голос
/ 01 августа 2020

Если вы хотите сравнить данные, содержащиеся в узле, то public class MyLinkedList<E extends Comparable<E>> - это путь к go, так как это гарантирует, что общий c тип E предоставляет compareTo(...) -метод. В этом случае реализация метода compareTo - это задача разработчика, пишущего тип.

Если вы определяете public class MyLinkedList<E> implements Comparable<E>, вы делаете узел, сопоставимый с E, но поскольку E является несвязанный, он в основном стирается до Object , и это действительно не дает вам реальной возможности сравнивать объекты . Поскольку можно получить доступ к переменной типа E только так, как если бы это была Object, у него практически нет доступа к соответствующей информации для реализации значимого порядка. Я бы поставил под сомнение такой заказ или, по крайней мере, попросил бы указать конкретный c вариант использования для этого заказа.

Два примечания:

Поскольку Java не поддерживает перегрузку операторов, нельзя записать

nodeA.data > something

, но вызвать compareTo -Метод и оценить его возвращаемое значение, например:

nodeA.data.compareTo(something) > 0

Существует также другой способ разрешить типы, которые не реализуют Comparable, путем принудительной передачи Comparator<E>. PriorityQueue использует этот подход.

0 голосов
/ 02 августа 2020

TL; DR : абсолютно возможно сравнить два Comparable параметризованных экземпляров некоторых типов c типа T<E> независимо от типа стирания.

Один ответ:

… но поскольку E не привязан, он в основном стирается до Object и это действительно не даст вам реальной возможности сравнивать объекты … «

Произошло стирание типа . Однако - , по крайней мере, в контексте процитированной выше гипотезы - стирание типа не является проблемой в этом контексте. Проблема в этом контексте и в том, что касается исходного вопроса: E в конечном итоге будет некоторым специфическим c типом, когда данный параметризованный тип создается фактическим аргументом типа на сайте использования .

@ Гипотеза Turing85 поднимает этот вопрос:

Q : Каким бы ни был окончательный тип E, является ли он обязательным для него реализовать Comparable, чтобы была «реальная возможность сравнения объектов»?

A : Нет . В контексте исходного вопроса речь идет не о E реализации Comparable. В этом контексте это примерно MyLinkedList реализация Comparable.

Объявление универсального класса c с параметром несвязанного типа E не исключает возможности сравнения объектов. Например, в некоторых случаях необходимо иметь MyLinkedList<MyLinkedList<Foo>>; где неограниченный E равен MyLinkedList<Foo> во внешнем параметризованном типе, а неограниченный E - это Foo во внутреннем параметризованном типе.

В эта рабочая демонстрация Я реализовал упрощенную репрезентативную модель связанного списка. В моей упрощенной модели Bar не реализует Comparable. MyLinkedList<E> сам по себе реализует Comparable<E>.

Пример использования…

public class Bar { 

    private int y;

    public Bar(int y){ 
        this.y = y;
    }               
}
...
MyLinkedList<Bar> list1 = new MyLinkedList<>();
MyLinkedList<MyLinkedList<Bar>> list2 = new MyLinkedList<>();
MyLinkedList<Bar> list3 = new MyLinkedList<>();
...
list1.add(new Bar(100));
list2.add(list3);  
list3.add(new Bar(101));
...
if (list2.compareTo(list1) != 0){ ... }
...
    

Щелкните зеленый Пуск кнопка вверху демо . Тогда вы можете заметить, что не имеет значения, что E не имеет границ в объявлении MyLinkedList<E>. Не имеет значения, что Bar не реализует Comparable.

Абсолютно возможно сравнение двух Comparable параметризованных экземпляры MyLinkedList<E> без проблем…

...
[node -> [node -> Bar: y=101]] is greater than [node -> Bar: y=100]
...

Стоит повторить: в моей демонстрационной модели Bar не реализует Comparable.

Также стоит отметить, что, независимо от стирания типа, то, что наблюдается в stdout, показывает, что независимо от типа среды выполнения node отображается здесь, в нем есть все опубликованные c, нестатистические c члены типа Bar.

0 голосов
/ 02 августа 2020

Если я полностью не понял ваш вопрос, то, поскольку вы сказали…

В основном, я пытаюсь сделать

if(nodeA.data > newData)
     //do something

… тогда для меня имеет смысл иметь параметр типа вашего Node орудия Comparable вместо параметра вашего List

public class LinkedList<E>{ 

    public static class Node<E extends Comparable<E>> {

        E data;

        Node<E> next;

        Node<E> prev;


        Node(Node<E> prev, E element, Node<E> next) {

            this.data = element;

            this.next = next;

            this.prev = prev;

        }
    
        public E getData( ){ return this.data; }

    }
}

Тогда каким бы ни был ваш data, он должен будет implement Comparable

public class Foo implements Comparable<Foo>{ 
    
    private int x;
    
    public Foo(int x){ this.x = x; }
    
    public int compareTo(Foo that){ 
        return this.x < that.x ? -1 : this.x == that.x ? 0 : 1;
    }
}

… разрешить вам нужно сделать что-то более близкое к тому, что вы указали в своем псевдокоде if(nodeA.data > newData) ...

public class DeduperAnswer{ 
    
    static public void main(String... args){ 
        
        LinkedList.Node<Foo> node1 = new LinkedList.Node<>(null, new Foo(10), null);
        LinkedList.Node<Foo> node2 = new LinkedList.Node<>(null, new Foo(20), null);
 
        if (node2.getData().compareTo(node1.getData()) > 0){ 
            /* ...this is NOT how you'd use it, of course...*/
        }
    }
}

Здесь вы можете увидеть быстрый и грязный рабочий пример .

...