【问题标题】:using TreeSet to sort without providing a Comparator to it使用 TreeSet 进行排序而不提供 Comparator
【发布时间】:2015-04-01 19:45:56
【问题描述】:

我知道java中的TreeSet会自动按升序对其元素进行排序,并保证顺序。

例如,如果我有一个随机的Date 对象数组并将其复制到TreeSet,那么它将以排序方式添加到TreeSet

但假设我不是一个简单的Date 对象,而是一个ArrayListHashMap<String,Object>,格式如下。

arraylist 中的第一个值,

{mydate = 32156464 , mystring = "abc", mystring2 = "xyz"}

hashmap 数组列表中的第二个值,

{mydate = 64687678 , mystring = "abdc", mystring2 = "xyzzz"}

hashmap 数组列表中的第三个值,

{mydate = 11233678 , mystring = "abxdc", mystring2 = "xyzppzz"}

现在,如果我想根据 mydate 键对这个 hashmap 的数组列表进行排序,我必须像这样在 TreeSet 实例中创建一个新的比较器,

public static Set<HashMap<String, Object>> mySet = new TreeSet<>(new Comparator<HashMap<String, Object>>() {
        @Override
        public int compare(HashMap<String, Object> o1, HashMap<String, Object> o2) {
            return ((Date) o2.get(mydate)).compareTo((mydate) o1.get(DATE));
        }
    }); 

它会将数组列表按排序顺序存储在TreeSet 中。但我使用了自定义Comparator 来实现这一点。如果我还为其提供自定义Comparator,那么在这种情况下使用TreeSet 对数据进行排序有什么意义?

如何在不使用TreeSetComparator 的新实例的情况下根据date 值对HashMap 中的ArrayList 进行排序?

【问题讨论】:

  • 排序容器的目的是让您的项目保持特定的顺序。比较器是您指定决定该顺序的因素的方法。

标签: java sorting arraylist


【解决方案1】:

在 TreeSet 中使用比较器的意义在于,您无需编写代码来进行实际排序,您只需提供一个方法,根据您的比较规则确定您的对象中的哪个是第一个。 如果您不想创建比较器,则需要将实现 Comparable 接口的对象添加到您的集合中。 要对 ArrayList 进行排序,请使用 Collections.sort()。

【讨论】:

    【解决方案2】:

    您可以创建一个包含 mydate、mystring、mystring2 并实现 Comparable 接口的类,而不是使用 HashMap。

    不过,使用比较器是一种很好的做法,因为您可以在运行时提供排序标准。

    【讨论】:

      【解决方案3】:

      如果您不向TreeSet 提供Comparator,那么它将依赖其元素Comparable 对它们进行排序。如果它们不是Comparable,则将产生ClassCastExceptionTreeSet javadocs解释:

      基于 TreeMap 的 NavigableSet 实现。元素使用它们的natural ordering 或在集合创建时提供的Comparator 进行排序,具体取决于使用的构造函数。

      但是HashMap 类不是Comparable,因此您必须提供自定义Comparator,以便TreeSet 知道您要如何对它们进行排序。您无法在没有Comparator 的情况下对HashMaps 进行排序,无论它们是在TreeSet 还是任何其他集合中。

      在这种情况下使用TreeSet 有很多好处。添加、查找和删除操作是 O(log n)。如果你为此使用ArrayList,那么添加和删除操作将是 O(n),即使查找操作仍然是 O(log n)。

      更多来自TreeSetjavadocs:

      此实现为基本操作(添加、删除和包含)提供有保证的 log(n) 时间成本。

      【讨论】:

        【解决方案4】:

        如果我还为其提供自定义比较器,那么在这种情况下使用 TreeSet 对数据进行排序有什么意义?

        因为是TreeSet 代码保持排序。您不必为此提供任何代码 - 所有您必须提供的只是自定义比较。

        如何在不使用 TreeSet 中新的 Comparator 实例的情况下根据日期值对 HashMap 的 ArrayList 进行排序?

        你不能,直接。你可以编写一个HashMap 的子类,它自己实现了Comparable,但这对我来说似乎有点奇怪。例如:

        public class SpecialMap extends HashMap<String, Object>
            implements Comparable<SpecialMap> {
        
            private final String key;
        
            public SpecialMap(String key) {
                this.key = key;
            }
        
            public int compareTo(SpecialMap other) {
                // TODO: Null handling
                Date thisDate = (Date) this.get(key);
                Date otherDate = (Date) other.get(key);
                return thisDate.compareTo(otherDate);
            }
        }
        

        然后你可以有一个ArrayList&lt;SpecialMap&gt; 并对其进行排序。

        但鉴于您必须提供与比较器基本相同的代码并且将您的比较与地图类型绑定,我觉得最好还是坚持比较器。

        【讨论】:

        • 您也可以将HashMap&lt;String, Object&gt; 包装在实现Comparable 的类中,但我同意这很奇怪。向TreeSet 提供Comparator 会更好。
        猜你喜欢
        • 2019-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-25
        • 1970-01-01
        • 2017-10-05
        • 2011-02-19
        • 1970-01-01
        相关资源
        最近更新 更多