为两个扩展超级的类制作比较器

时间:2013-10-16 09:09:04

标签: java generics inheritance collections comparator

我对我对仿制药的有限知识表示道歉

我有以下情况:

第1课:

public class PostProcess implements Serializable {
    public int          order;
    // Several other variables.

    // Constructor setting vars
    public PostProcess(){

    }

    /* Getters and setters for variables */
}

第2课:

public class Application extends PostProcess{
    public int      subOrder;
    // Several other variables.

    // Constructor setting vars
    public Application(){

    }

    /* Getters and setters for variables */

}

第3课:

public class FileOperation extends PostProcess{
    public int      subOrder;
    // Several other variables (different from class 'Application').

    // Constructor setting vars
    public FileOperation(){

    }

    /* Getters and setters for variables */

}

我想在另一个类中实现的是对包含'FileOperation'和'Application'对象组合的列表进行排序,定义如下:

private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();

此类必须位于这两个对象的两个字段中,即:'order'和'subOrder'。 'order'继承自PostProcess,'subOrder'在'Application'和'FileOperation'类中定义。

在我阅读泛型,可比较,比较器和界面的过程中,我认为我把事情弄得一团糟。

我正在尝试使用以下方式应用排序:

Collections.sort(processList, new PostProcessComparator());

PostProcessComparator定义为:

public class PostProcessComparator implements Comparator<? extends PostProcess> {

    @Override
    public int compare(Object p1, Object p2) {

      int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
      if (mainOrderCompare != 0) {
        return mainOrderCompare;
      } else {
        return p1.getSubOrder().compareTo(p2.getSubOrder());
      }
    }
}

问题:

我知道我的比较器(可能更多)是错误的,但我不知道具体在哪里。我来这里学习;)

  1. 我注意到定义'processList'列表不是正确的方法。当我尝试将“FileOperation”或“Application”对象添加到List时,编译器会在“没有找到适合添加的方法(应用程序)”的情况下对我进行打击(对于FileOperation也是如此)。我是否错误地认为我可以使用泛型来声明我的processList类型?应该是正确的,因为两个类都有PostProcess作为他们的超类吗?
  2. 定义具有类边界的PostProcessComparator应该在我眼中工作,因为我只希望能够比较具有PostProcess作为超类的对象(因此可以访问相同的方法)。
  3. 如何在pa和p2的Comparator类中访问有争议的对象(因为我仍然需要为参数声明它们的类型:

    @Override
    public int compare(<What to put here?> p1, <And here?> p2) {
    
    }
    
  4. 我真的希望你们能帮忙! 如果我不清楚某些事情,请告诉我并详细说明。

    谢谢!

    修改

    感谢NickJ和Winzu,我对比较器和ArrayList定义进行了必要的更改。

    • 我已将subOrder从Application和FileOperation移至父类(并使其受到保护)
    • 将比较器的参数化重新定义为:

      public class PostProcessComparator<T extends PostProcess> implements Comparator<T> 
      
    • 利用Integer.compare(p1.getOrder(),p2.getOrder())进行初始比较器比较。

    现在是最后的挑战(编译器警告) 致电:

        Collections.sort(processList, new PostProcessComparator());
    

    我收到警告: - [未选中]未经检查的方法调用:类集合中的方法排序应用于给定类型

        required:  List<T>,Comparator<? super T>
        found: ArrayList<PostProcess>,PostProcessComparator
    

    除了我没有检查对象类型的事实外,参数化在我眼中对于这个比较器是正确的。

    哪里出错了?

3 个答案:

答案 0 :(得分:4)

我发现的唯一问题是你需要像这样参数化PostProcessComparator:

public class PostProcessComparator<T extends PostProcess> implements Comparator<T> {

  @Override
  public int compare(T p1, T p2) {

    int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
    if (mainOrderCompare != 0) {
      return mainOrderCompare;
    } else {
      return p1.getSubOrder().compareTo(p2.getSubOrder());
    }
  }
}

现在compare()方法将接受正确的类(扩展PostProcess),因此可以从comlpare()

中调用PostProcess的所有公共方法。

最后,您的字段不应公开。我建议保护字段,因此子类仍然可以继承它们,但保持封装。

答案 1 :(得分:2)

NickJ上面的回答显示了如何实施比较器。

对于你正在做的事情,你也想改变

private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();.

ArrayList<PostProcess> processList = new ArrayList<PostProcess>();

这就是您无法将Application et FileOperation对象添加到列表中的原因。

这有点棘手。也许这篇文章可以帮助您理解

Java using generics with lists and interfaces

您还希望父类中的SubOrder。

import java.io.Serializable;

public class PostProcess implements Serializable {
private int          order;
private int      subOrder;
// Several other variables.

public int getSubOrder() {
    return subOrder;
}

public void setSubOrder(int subOrder) {
    this.subOrder = subOrder;
}

public int getOrder() {
    return order;
}

public void setOrder(int order) {
    this.order = order;
}

// Constructor setting vars
public PostProcess(){

}

}

最后像这样调用比较器以避免未经检查的警告:

 Collections.sort(processList, new PostProcessComparator<PostProcess>());

答案 2 :(得分:0)

只需将其更改为:

public class PostProcessComparator implements Comparator<PostProcess> {
    @Override
    public int compare(PostProcess p1, PostProcess p2) {
      //...
    }
}

就是这样。您有一个比较器,可以比较PostProcess的任意两个实例(PostProcess的子类实例是PostProcess的实例。)