【问题标题】:Binary search on arrays/comparator using generics Java使用泛型 Java 对数组/比较器进行二进制搜索
【发布时间】:2012-10-02 03:22:18
【问题描述】:

我正在努力使二进制搜索的比较器在对象数组上工作。本质上,目标是搜索参差不齐的数组以找到项目的第一个匹配项或最接近的匹配项以提供插入点。该方法传入一个泛型(这是不可更改的 - 因为这是家庭作业),但你不能创建泛型类型的数组......所以,我的比较器抛出一个错误:“方法 binarySearch(Object[], Object) in类型数组不适用于参数 (Object[], E, Comparator)”。也许我需要转换通用元素“项目”?我不知道。代码:

private Location findFirst(E item) {
    Location current;
    int closestMatchArray1;
    int closestMatchArray2;

Object[] firstItemInArray2 = new Object[numArrayInUse];
Object firstItem;

Comparator<E> comparator = new CompareElement();

for (int i - 0; i < numArrayInUse; i++) {
    firstItem = topArray[i];
    firstItemInArray2[i] = firstItem;
}

closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);

次要但相关的问题。在比较器中,我试图调用 Comparable 方法“compareTo”来获取一个负整数,该整数给出了一个项目在失败搜索时位于数组中的大致位置,但同样,我遇到了麻烦使用泛型,出现此错误:“未定义类型 E 的方法 compareTo(E)”。代码:

public class CompareElement implements Comparator<E> {
  public int compare(E firstItem, E secondItem) {
     return firstItem.compareTo(secondItem);
  }
}

【问题讨论】:

  • 您能否准确告诉我们您收到了哪些错误消息以及何时/何地?
  • 不能使用 List,虽然它会很好。错误消息是:“数组类型中的方法 binarySearch (Object[], Object) 不适用于参数 (Object[], E, Comparator)。并且“方法 compareTo(E) 未定义键入 E"。
  • @KingTriumph - 使用该错误更新您的帖子。
  • 你有一个名为E的类吗?
  • “未定义类型 E 的方法 compareTo(E)”compareTo 是来自 Comparable 的方法。在您的CompareElement 类中,必须声明E,即public class CompareElement&lt;E extends Comparable&gt; implements Comparator&lt;E&gt;

标签: java arrays generics search binary


【解决方案1】:

您必须传递Class&lt;E&gt;,以便实例化E 的数组。 (由于&lt;E&gt; 在运行时被删除,E 只是对象。)

Class<E> klazz;

E[] firstItemInArray2 = (E[])
        java.lang.reflect.Arrays.newInstance(klazz, numArraysInUse);

【讨论】:

    【解决方案2】:

    您没有声明&lt;E&gt;。您必须按如下方式定义您的 CompareElement

    public class CompareElement<E extends Comparable> implements Comparator<E> {
        public int compare(E firstItem, E secondItem) {
            return firstItem.compareTo(secondItem);
        }
    }
    

    然后声明如下:

    Comparator<?> comparator = new CompareElement<?>();
    

    ? 应该是您要比较的类型。

    【讨论】:

      【解决方案3】:

      您的E 在哪里声明?看起来像是在我们看不到的某个封闭类中声明的某些类型参数。您的CompareElement 类似乎是一个比较器,它根据元素的自然顺序(即根据Comparable)比较元素。如果是这样,那么E 必须有一个边界来保证它能够与自身进行比较,&lt;E extends Comparable&lt;? super E&gt;&gt;。您可以更改声明 E 的边界,或者,如果您想像其他人建议的那样,将 CompareElement 与封闭类分开参数化,您可以这样做:

      public class CompareElement<E extends Comparable<? super E>> implements Comparator<E> {
        public int compare(E firstItem, E secondItem) {
           return firstItem.compareTo(secondItem);
        }
      }
      

      您的第一个错误是因为您尝试使用的binarySearch 版本(带有比较器的版本)对参数类型有限制。声明如下:static &lt;T&gt; int binarySearch(T[] a, T key, Comparator&lt;? super T&gt; c)。所以如果你有一个Comparator&lt;E&gt;,那么你需要一个E[]作为第一个参数,而你有一个Object[]。你得想办法让它E[]

      但实际上对于您而言,您根本不需要使用比较器。 binarySearch 方法的一个版本不使用比较器,它已经使用自然顺序比较元素。

      【讨论】:

        【解决方案4】:

        我认为您要么需要Comparator&lt;Object&gt;,要么需要E[] 的数组。对于后者,我建议查看这两篇文章:

        鼓励阅读。


        选项 1:Array.newInstance()

        假设 item 永远不会为空

        根据我在上述帖子中读到的内容,如果您知道 item 永远不会是 null,您可以尝试这样的事情...

        @SuppressWarnings("unchecked")
        private Location findFirst(E item) {
            Location current;
            int closestMatchArray1;
            int closestMatchArray2;
        
            // Object[] firstItemInArray2 = new Object[numArrayInUse];
            // Object firstItem;
        
            E[] firstItemInArray2 
                    = (E[]) Array.newInstance(item.getClass(), numArrayInUse); 
            E firstItem;
        
            Comparator<E> comparator = new CompareElement();
        
            for (int i = 0; i < numArrayInUse; i++) {
                firstItem = (E) topArray[i];
                firstItemInArray2[i] = firstItem;
            }
        
            closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);
        

        选项 2:Array.newInstance()

        需要类参数

        如果不能保证item永远不会是null,又不能对null的值进行特殊处理,可以强制传入Class&lt;?&gt;参数,如下.. .

        @SuppressWarnings("unchecked")
        private Location findFirst(E item, Class<E> clazz) {
            Location current;
            int closestMatchArray1;
            int closestMatchArray2;
        
            // Object[] firstItemInArray2 = new Object[numArrayInUse];
            // Object firstItem;
        
            E[] firstItemInArray2 
                    = (E[]) Array.newInstance(clazz, numArrayInUse); 
            E firstItem;
        
            Comparator<E> comparator = new CompareElement();
        
            for (int i = 0; i < numArrayInUse; i++) {
                firstItem = (E) topArray[i];
                firstItemInArray2[i] = firstItem;
            }
        
            closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);
        

        选项 3:对象比较器包装器

        很丑,但是可​​以用

        或者,您可以创建一个 Comparator&lt;Object&gt; 来包装您现有的 Comparator&lt;E&gt;,如下所示(我认为这有点 hack,但它对我来说始终如一)...

            private Location findFirst(E item) {
            Location current;
            int closestMatchArray1;
            int closestMatchArray2;
        
            Object[] firstItemInArray2 = new Object[numArrayInUse];
            Object firstItem;
        
            // Comparator<E> comparator = new CompareElement();
            Comparator<Object> comparator = new Comparator<Object>() {
                private final Comparator<E> delegate = new CompareElement();
        
                @Override
                @SuppressWarnings("unchecked")
                public int compare(Object o1, Object o2) {
                    return delegate.compare((E) o1, (E) o2);
                }
            };
        
            for (int i = 0; i < numArrayInUse; i++) {
                firstItem = topArray[i];
                firstItemInArray2[i] = firstItem;
            }
        
            closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);
        

        希望这会有所帮助!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-10-25
          • 2013-09-29
          • 2012-09-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-25
          • 1970-01-01
          相关资源
          最近更新 更多