为不同 类 的通用链表实现 Comparable

Implement Comparable for generic Linked List for different classes

首先:我不是要重新发明轮子,这是为了学习。

我是 世界的新手,所以请耐心等待。

我的目标是构建一个 public class 来管理带排序插入的链表。

到目前为止我所做的(有效的)是:

import java.util.Iterator;

import package_Car.SortTypes;

class Node<E>
{
    E data;
    Node<E> next;

    Node(E data, Node<E> node)
    {
        this.data = data;
        this.next = node;
    }

    public Node<E> getNext()
    {
        return next;
    }
}

public class SortedInsertionLinkedList<E> implements Iterable<Node<E>>
{
    Node<E> root;
    Sort_Types sort;

    final class LinkedListIterator implements Iterator<Node<E>>
    {
        private Node<E> cursor;

        LinkedListIterator(Node<E> root)
        {
            cursor = new Node<E>(null, null);
            cursor = root;
        }

        public boolean hasNext()
        {       
            return cursor != null;
        }

        public Node<E> next()
        {
            Node<E> retVal = cursor;

            if (hasNext())
            {
                cursor = retVal.getNext();
            }

            return retVal;      
        }
    }   

    public Iterator<Node<E>> iterator()
    {
        return new LinkedListIterator(root);
    }

    public SortedInsertionLinkedList(Sort_Types sort)
    {
        root = null;
        this.sort = sort;
    }

    public void insert(E item)
    {
        if (item != null)
        {
            if (root == null)
            {
                root = new Node<E>(item, null);
            }
            else
            {
                Node<E> currNode = root;
                Node<E> prevNode = null;

                for (Node<E> currListNode : this) 
                {
                    if (sort.compareTo(currListNode.data, item) < 0)
                    {
                        prevNode = currListNode;
                        currNode = currListNode.next;
                    }
                }

                Node<E> t = new Node<E>(item, currNode);

                if (prevNode == null)
                    root = t;
                else
                    prevNode.next = t;

            }
        }
    }

    public void print()
    {
        for (Node<E> currNode : this)
        {
            System.out.print(currNode.data + " ");
            System.out.println();
        }
        System.out.println();
    }

    public boolean find(E x)
    {
        for (Node<E> currNode : this)
        {
            int c = sort.compareTo(currNode.data, x);

            if (c == 0)
                return true;
            if (c > 0)
                return false;
        }
        return false;
    }

    public void delete(E x)
    {
        Node<E> prevNode = null;
        for (Node<E> currNode : this)
        {
            int c = sort.compareTo(currNode.data, x);
            if (c == 0)
            {
                if (currNode == root)
                {
                    root = currNode.next;
                }
                else
                {
                    prevNode.next = currNode.next;
                }

                return;
            }
            if (c > 0)
                return;

            prevNode = currNode;
        }
    }
}

如您所见,我在 class 中添加了一个私有字段,用于定义必须使用哪种类型的排序来比较链表节点。这种排序类型是枚举

public enum Sort_Types
{
    SORT_BY_NAME
    {
        public int compareTo(Object o1, Object o2)
        {
            Car item1 = (Car) o1;
            Car item2 = (Car) o2;

            return item1.nome.compareTo(item2.nome);
        }
    },
    SORT_BY_PRICE
    {
        public int compareTo(Object o1, Object o2)
        {
            Car item1 = (Car) o1;
            Car item2 = (Car) o2;

            return Double.compare(item1.prezzo, item2.prezzo);
        }
    },
    SORT_BY_GAIN
    {
        public int compareTo(Object o1, Object o2)
        {
            double gain1;
            double gain2;

            if (o1 instanceof CarSpecificInterface)
            {
                CarSpecificInterface dummy = (CarSpecificInterface) o1;
                gain1 = dummy.gain();
            }
            else
            {
                throw new IllegalArgumentException();
            }

            if (o2 instanceof CarSpecificInterface)
            {
                CarSpecificInterface dummy = (CarSpecificInterface) o2;
                gain2 = dummy.gain();
            }
            else
            {
                throw new IllegalArgumentException();
            }

            return Double.compare(gain2, gain1);
        }
    },
    SORT_BY_URGENCY
    {
        public int compareTo(Object o1, Object o2)
        {
            double urgency1;
            double urgency2;

            if (o1 instanceof CarSpecificInterface)
            {
                CarSpecificInterface dummy = (CarSpecificInterface) o1;
                urgency1 = dummy.urgency();
            }
            else
            {
                throw new IllegalArgumentException();
            }

            if (o2 instanceof CarSpecificInterface)
            {
                CarSpecificInterface dummy = (CarSpecificInterface) o2;
                urgency2 = dummy.urgency();
            }
            else
            {
                throw new IllegalArgumentException();
            }        

            return Double.compare(urgency2, urgency1);
        }
    };

    public abstract int compareTo(Object o1, Object o2);
}

我为什么这么做?因为可以用来实例化链表的class是3:

  1. Car
  2. New_Carextends Car
  3. Used_Carextends Car

New_CarUsed_Car classes 实现了一个接口

public interface Car_Specific_Interface
{
    public double gain();
    public double urgency();
}

所以我可以将我的链表用于可以接受(显然)子类的 Car 类型

Sorted_Linked_List<Car> carsSortedByName;
Sorted_Linked_List<Car> carSortedByGain;
Sorted_Linked_List<Car> carSortedByUrgency;

public DB_Mng()
{
    carsSortedByName = new Sorted_Linked_List<>(Sort_Types.SORT_BY_NAME);
    carSortedByGain = new Sorted_Linked_List<>(Sort_Types.SORT_BY_GAIN);
    carSortedByGain = new Sorted_Linked_List<>(Sort_Types.SORT_BY_URGENCY);
}

所以,总结一下:我有一个 带有排序插入 的通用链表,它可以接受不同的 classes 并且可以按特定字段或方法排序。

我想了解的是,是否有办法改变 classes 层次结构 "simply" 实现 Comparable 接口。

我建议完全退后一步。有了 Java8 和 lambdas 以及流,2017 年的事情确实有所不同。或者好吧,多年来。

我建议您从 Java 斯图加特 2014 论坛中查看此 presentation。一些德语的开头词,但其余都是代码,并且易于掌握。

事情是:你想写这样的代码:

collection .sort(
  Comparator
  .comparing(Person::getName)
  .reversed()
  .thenComparing(Person::getId)
);

并使用 lambdas / 方法引用 - 而不是编写所有 "manual boilerplate" 代码来访问成员字段。

第一步是了解 java 泛型。 具体来说, java 泛型是一个编译时特性; 它们绝不是 c++ 模板的 java 实现。

您无法创建 "fully general" 插入时排序列表,因为 Object 未实现任何比较功能。

您可以创建一个插入时排序的元素列表,这些元素实现了一些已知的接口或扩展了特定的 class。

如果 NewCarUsedCar 都在实现 Car_Specific_Interface,您可以只检查比较器中的接口,例如:

        if (o1 instanceof Car_Specific_Interface)
        {
            Car_Specific_Interface dummy = (Car_Specific_Interface) o1;
            gain1 = dummy.gain();
        }
        else
        {
            throw new IllegalArgumentException();
        }

你也可以让你比较复杂的功能来支持ComparableComparator。例如:

private int compareItems(E firstItem, E secondItem) {
    if (sort == null) {
        if (firstItem instanceof Comparable && secondItem instanceof Comparable) {
            return ((Comparable)firstItem).compareTo(secondItem);
        } else {
            throw new IllegalArgumentException("Failed to compare");
        }
    } 
    return sort.compareTo(firstItem, secondItem);
}