Реализация remove (Object o) в общей коллекции - PullRequest
0 голосов
/ 17 мая 2018

Я пишу общую коллекцию, основанную на модели двоичного дерева.

class MyTree <T extends Comparable<T>> extends AbstractCollection<T>{...}

Базовый класс Node<T> (среди прочих) содержит следующие методы:

public Node<T> getLeft()  // left Node
public Node<T> getRight() // right Node
public T getValue()       // value stored in the Node

Я хочу переопределить метод boolean contains(Object o) интерфейса AbstractCollection<T>, чтобы иметь возможность проверить наличие Object типа, отличного от T.

Для обхода дерева в O (log n) универсальный тип T должен реализовывать Comparable<T>, поэтому он имеет метод compareTo(T t).

Мой код:

@Override
public boolean contains(Object o){
    T t = (T) o; // produces warning (see below)
    BSNode<T> currentNode = this.root;
    while(currentNode != null){
        if(currentNode.getValue().equals(o)) {return true;}
        if(currentNode.getValue().compareTo(t) < 0)  {currentNode = currentNode.getRight();}
        if(currentNode.getValue().compareTo(t) > 0)  {currentNode = currentNode.getLeft();}
    }
    return false;
}

Проблема в том, что я не могу просто привести Object o к T t для использования compareTo(T t). Технически Object можно преобразовать в T, но, поскольку T является универсальным типом, я получаю это предупреждение:

warning: [unchecked] unchecked cast
          T t = (T) o;
                    ^
required: T
found:    Object
where T is a type-variable:
  T extends Comparable<T> declared in class MyTree

Может кто-нибудь либо

  1. подтвердите, что я могу безопасно игнорировать предупреждение, используя @SuppressWarnings("unchecked"),
  2. подскажите, как можно безопасно привести Object к T,
  3. объясните, почему ни один из вышеперечисленных пунктов не может быть удовлетворен, поэтому я могу перестать думать о том, как заставить это работать?

Большое спасибо!

1 Ответ

0 голосов
/ 17 мая 2018

Если вы хотите проводить неограниченные поиски, вам нужно выполнить приведение. Вы можете добавить instanceof для защиты приведения от исключений, но это тоже не идеально.

Рассмотрите возможность изменения границ T следующим образом:

class MyTree <T extends Comparable<? super T>> extends AbstractCollection<T>{...}

Поскольку вы делаете переопределение, подавление предупреждения в значительной степени требуется. Актерский состав должен выглядеть следующим образом:

@SuppressWarnings("unchecked")
Comparable<? super T> t = (Comparable<? super T>) o;

См. Источник getEntry метода java.util.TreeMap для примера того, как это делается в Java source (они делают это по той же причине - необходимость переопределить метод с подписью принимая Object).

...