如何用compareTo()对TreeSet按字母排序?及Movies集合按演员名去重排序
TreeSet 本身就依赖 Comparable 接口的 compareTo() 方法维护元素顺序,实现字母顺序排序其实很直接,分两种场景:
针对String等已实现Comparable的类:String类自带了按Unicode(日常用的字母顺序)排序的
compareTo()实现,直接把元素放进TreeSet就会自动按字母顺序排列,比如:TreeSet<String> stringSet = new TreeSet<>(); stringSet.add("Banana"); stringSet.add("Apple"); stringSet.add("Cherry"); // 遍历输出顺序就是 Apple, Banana, Cherry针对自定义类(比如你的Movie类):需要让类实现
Comparable<Movie>接口,在compareTo()方法里指定按目标字符串字段(比如演员名字)的字母顺序比较,这部分我会在问题2里讲正确的写法。
先直接点出你的compareTo()方法的核心问题:你在方法里遍历了外部的moviesList,这完全搞错了compareTo()的作用!这个方法的本质是比较当前对象(this)和传入的参数对象(m),跟外部集合没有关系。
第一步:修复compareTo()方法
正确写法应该直接对比当前Movie的演员名字和传入Movie的演员名字,这样TreeSet既能按演员字母排序,又能把演员名字相同的元素判定为重复(compareTo()返回0时,TreeSet会认为两个元素相等,自动去重):
public class Movie implements Comparable<Movie> { private String actor; // 其他字段、构造方法、getter/setter省略 @Override public int compareTo(Movie m) { // 可选:处理null场景,避免空指针 if (this.actor == null && m.actor == null) return 0; if (this.actor == null) return -1; if (m.actor == null) return 1; // 按演员名字的字母顺序比较 return this.actor.compareTo(m.actor); } }
第二步:把ArrayList转成TreeSet实现排序去重
这一步非常简单,直接用TreeSet的构造方法传入你的ArrayList即可,TreeSet会自动调用你写好的compareTo()完成排序和去重:
ArrayList<Movie> moviesList = new ArrayList<>(); // 先往moviesList中添加你的Movie对象 // 转换为TreeSet自动完成排序+去重 TreeSet<Movie> sortedUniqueMovies = new TreeSet<>(moviesList); // 遍历验证结果 for (Movie movie : sortedUniqueMovies) { System.out.println(movie.getActor()); }
额外提醒
如果你的去重逻辑需要考虑更多字段(比如演员名字相同但电影名不同,不想算作重复),那还需要重写equals()和hashCode()方法,但TreeSet主要依赖compareTo()判断元素相等,要是你的需求就是按演员去重,上面的写法就足够了。
内容的提问来源于stack exchange,提问作者new programmer

