【问题标题】:How to write a generic findMax() method using collections.max()?如何使用 collections.max() 编写通用 findMax() 方法?
【发布时间】:2016-08-18 16:43:03
【问题描述】:

我正在尝试创建一个通用方法 findMax(List list),它接受 LocalDate 列表或日期类型列表,并返回列表中的最大值。

Collections.max(List LocalDate) 和 Collections.max(List Date) 都可以正常工作,但我不知道如何让它返回正确的类型。

不太了解比较器在 Java 中的工作原理。

下面是我的尝试

static List<LocalDate> localDateList = new ArrayList<LocalDate>();
static List<Date> dateList = new ArrayList<Date>();

private <T> T findMax(List<T> list) {
    return Collections.max(list);
}

public static void main(String[] args) throws ParseException, SQLException, JsonProcessingException {

    localDateList.add(new Date(11 * 86400000).toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
    localDateList.add(new Date(22 * 86400000).toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
    localDateList.add(new Date(3 * 86400000).toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
    localDateList.add(new Date(14 * 86400000).toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
    localDateList.add(new Date(65 * 86400000).toInstant().atZone(ZoneId.systemDefault()).toLocalDate());

    dateList.add(new Date(11 * 86400000));
    dateList.add(new Date(22 * 86400000));
    dateList.add(new Date(3 * 86400000));
    dateList.add(new Date(14 * 86400000));
    dateList.add(new Date(65 * 86400000));

    System.out.println(Collections.max(localDateList));
    System.out.println(Collections.max(dateList));

    System.out.println(findMax(localDateList));
    System.out.println(findMax(dateList));

}

已编辑: 通过从

更改使其工作
private <T> T findMax(List<T> list) {
    return Collections.max(list);
}

private <T extends Object & Comparable<? super T>> T findMax(List<T> list) {
    return Collections.max(list);
}

【问题讨论】:

  • Collections.max 已经返回“正确”类型。例如,String s = Collections.max(yourListOfString) 将编译。
  • 贴出的代码有什么问题?为什么你试图将 Collections.max() 包装成一个做同样事情的方法?如果你真的想要,为什么不使用与 Collections.max() 完全相同的泛型类型?
  • 它告诉你它是一个对象,因为类型擦除。泛型类型仅在编译时由编译器知道,并且仅在那时才相关。他们在那里尽可能避免不安全的演员表。
  • @OuYe 顺便说一下,java.time 类取代了旧的 java.util.Date/.Calendar 类。不打算混合。坚持使用 java.time。仅在需要处理尚未更新为 java.time 类型的旧代码时才使用旧类。
  • 如果你想编译你的findMax 方法,你必须将你的findMax 方法的泛型类型从&lt;T&gt; 更改为&lt;T extends Object &amp; Comparable&lt;? super T&gt;&gt;,但我不明白这一点。

标签: java generics collections


【解决方案1】:

Collections.max()

无需编写您的findMax 方法。 Collections.max 已经为您做到了。

List<LocalDate> localDates = new ArrayList<> ( 3 );
LocalDate today = LocalDate.now ( ZoneId.of ( "America/Montreal" ) );
localDates.add ( today );
localDates.add ( today.plusDays ( 2 ) );
localDates.add ( today.minusDays ( 4 ) );

LocalDate max = Collections.max ( localDates );

转储到控制台。

System.out.println ( "localDates: " + localDates + " | max: " + max );

本地日期:[2016-08-18, 2016-08-20, 2016-08-14] |最大值:2016-08-20

比较

任何实现Comparable 接口的类都必须实现compareTo 方法。该方法必须返回一个负整数、零或一个正整数,因为该对象小于、等于或大于另一个相同类型的对象。

LocalDate 类实现了这个compareTo 方法。

Collections.max 方法循环集合的元素,例如 List,并调用每个对象的 compareTo 方法。所有这些都是为您完成的,以减轻您编写此类代码的苦差事。

泛型

评论表明这个问题实际上更多是关于Java Generics,而不是关于比较。

这是一个实现 findMax 方法的示例。我在 OpenJDK 项目中按照 Java 8 的 Collections.max source code 的示例进行操作。

正如我上面所说,仅将调用包装到Collections.max 并没有任何生产用途。但它确实是使用泛型的一个很好的实验示例。

public <T extends Object & Comparable<? super T>> T findMax ( Collection<? extends T> coll ) {
    T maximum = Collections.max ( coll );
    return maximum;
}

调用该方法并传递上面看到的localDates 集合。

System.out.println ( "findMax: " + this.findMax ( localDates ) );

【讨论】:

  • 你知道他们为什么使用Object &amp; Comparable吗?据我了解,一切都是对象,T extends Comparable 将直接编译。我想弄清楚。
  • 啊我明白了,这是为了保持与预泛型 API 的兼容性,强制类型为 Object 擦除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多