【问题标题】:Anonymous Inner Class - Collections sort匿名内部类 - 集合排序
【发布时间】:2016-05-02 20:24:48
【问题描述】:

我正在创建一个比较器作为匿名内部类,我不确定它是否是最好的方法。我在我的代码中只创建了一次,但我不确定每次我对列表进行排序时是否创建了该内部类。例如,在一个应用程序中,如果我使用该比较器调用 sort 方法 10 次,是否会创建十个额外的类?

Collections.sort(originalList, new Comparator<User>() {
    @Override
    public int compare(User o1, User o2) {
        int value1 = o1.getPropertyCode().compareTo(o2.getPropertyCode());
        if (value1 == 0) {
            int value2=o1.getPropertyValue().compareTo(o2.getPropertyValue());
            return value2;
        }
        return value1;
    }
});

Collections.sort(originalList, new SomeComparator());

【问题讨论】:

  • 代码值一千字!给我们看看!
  • 如果“创建十个额外的类”是指 10 个实例,那么答案是肯定的。 (这就是 new 关键字的作用)
  • ...但是这 10 个额外的实例实际上对性能有显着影响吗?在特定情况下,也许;一般来说,不。
  • @user2296988 如果你的意思是你有 10 个不同的匿名类,你认为这有什么不同吗?一旦它们被类加载器加载,它只是创建实例。

标签: java


【解决方案1】:

匿名类被编译器转换为常规类定义,并且实际上被赋予了一个类似 OutterClass$1 的名称,您不能通过该名称引用该类,但您可以通过例如 new Object() {}.class.getName() 来查看它总是相同。每当您的代码遇到问题时,它只使用 1 个类 - 无论您是否给它一个明确的名称。您的 2 个选项基本相同。

但是当您阅读直到Collections.sort(originalList, new 之前的代码行时,您应该知道new 每次都会创建一个新实例(而不是类)。 IE。它分配内存,初始化事物,.. 这些都不需要多次,因为创建的比较器对象永远不会不同。

您想要做的是将创建的比较器存储在这样的字段中一次(或者像在 Java 自己的源代码 String.CASE_INSENSITIVE_ORDER 中一样)

private static final Comparator<User> USER_COMPARATOR = new Comparator<User>() {
    @Override
    public int compare(User o1, User o2) {
        int value1 = o1.getPropertyCode().compareTo(o2.getPropertyCode());
        if (value1 == 0) {
            int value2=o1.getPropertyValue().compareTo(o2.getPropertyValue());
            return value2;
        }
        return value1;
    }
};
private void someCode() {
    Collections.sort(originalList, USER_COMPARATOR);
}

或者使用 Java 8,您可以将其转换为 lambda(注意缺少 new),它也不会每次都创建新实例

Collections.sort(originalList, (o1, o2) -> {
    int value1 = o1.getPropertyCode().compareTo(o2.getPropertyCode());
    if (value1 == 0) {
        int value2=o1.getPropertyValue().compareTo(o2.getPropertyValue());
        return value2;
    }
    return value1;
});

【讨论】:

  • 如果你要把它变成一个 lambda,你还不如写一个更紧凑的 comparing(User::getPropertyCode).thenComparing(User::getPropertyValue)
  • 非常好,不知道在 String 类中使用了这个。这应该变得更流行,就像设计模式一样。并不是说额外的课程总是有记忆问题,但我相信它对我的情况很有帮助。
  • @LouisWasserman 的缺点是这不会产生像 lambda 这样的静态字段,而是会在每次代码运行时生成。可能不是在 JIT 得到它之后.. 但无论如何,在这种情况下我会将它分配给一个静态字段
【解决方案2】:

这取决于。如果您在方法中有该比较器,那么在每次调用时都会实例化一个新的。此外,该 Comparator 将包含对包含类的引用。

另一方面,如果您将匿名内部类定义为静态字段,那么将只有一个(每个类加载器)。

【讨论】:

  • 如何将其声明为静态字段?像静态初始化块?
猜你喜欢
  • 1970-01-01
  • 2011-07-06
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 2019-08-29
  • 1970-01-01
相关资源
最近更新 更多