【问题标题】:Sort a List of Map<String, String> [duplicate]对 Map<String, String> 的列表进行排序 [重复]
【发布时间】:2014-09-05 12:52:56
【问题描述】:

我看到了这个帖子 sorting a List of Map<String, String>,我知道我的帖子听起来可能是重复的,但略有不同。

我的例子是:

List<Map<String, String>> myList = new ArrayList<Map<String, String>>();

...
for(MyClass1 c1 : c1)
{
  ...
  for(MyClass2 c2 : c12)
  {
    SimpleBindings myBindindings= new SimpleBindings();
    myBindindings.put(c1.getName(), c2.getName());

    myList.add(myBindindings);
  }
}
...

具体来说我可以拥有

{
 (John, Mike)
 (John, Jack)
 (Sam, Jack)
 (Gloria, Anna)
 (Jane, Carla)
 ...
}

并且希望我的列表按 maps 键排序:

{
  (Gloria, Anna)
  (Jane, Carla)
  (John, Mike)
  (John, Jack)
  (Sam, Jack)
  ...
}

【问题讨论】:

  • 有什么不同?您是否尝试像建议的答案那样编写比较器?你尝试了什么?
  • 你到底在排序什么?你有一个List(一个集合)Map(另一个集合)。您如何确定一个Map 是否大于另一个?此外,您要添加 SimpleBindings 而不是 Map - 如果此类 extends Map 考虑这样做,最好避免在 Java 集合框架中扩展项目。
  • 所以你的Maps 每个只有 1 个键值对?为什么不直接使用TreeMap&lt;String, String&gt; 呢?
  • @Mena 这也是我的怀疑 - 如果是这种情况,那么 Map 完全是错误的结构,因为显然不需要查找。 TreeSet 的一些自定义对象可能是最好的。
  • 为什么(John, Mike)(John, Jack)之前?

标签: java sorting collections


【解决方案1】:

你确定

List<Map<String, String>>

是您想要的合适的数据类型吗?

在我看来,您实际上是在寻找简化

TreeMap<String, String>

即排序后的映射键 -> 值?

或者您的意思是使用List&lt;StringPair&gt;(为此,请选择比StringPair 更合适的名称,并根据您的需要实现该类)?我的印象是,由于 Java 中没有明显的 Pair&lt;String, String&gt; 类,你一直在滥用 SimpleBinding 作为一对类。在 Java 中实现对的正确方法是实现一个新类,并使用正确的类名——“对”是技术性的,而不是语义性的。

你也可以

List<String[]>

并实现Comparator&lt;String[]&gt; 进行排序。但这并不能为您节省任何实现 NamePair 类并让您自己进行比较的工作。

【讨论】:

  • 如果是 TreeMap,您将删除重复项。
  • 这很可能是需要的。例如,如果他不想这样做,他可以使用来自 Guava 的TreeMultimap。 (刚刚意识到他的例子中确实有这种情况 - 但可能不是故意的)。
  • OP 正在使用 SimpleBindings 类型,其中 extends Map。我认为出于某种原因需要这种类型 - 也许作为另一种方法的输入。
  • 我不相信这是必需的,但我相信它是在缺少Pair 类时偶然使用的。
  • 我选择这个答案是因为Map(通常)不是合适的数据类型。
【解决方案2】:

你需要实现 Comparator 来完成这个...

Collections.sort(myList, new Comparator<ObjectBeingCompared>() {

            @Override
            public int compare(ObjectBeingCompared obj1, ObjectBeingCompared obj2) {

                //Of course you will want to return 1, 0, -1 based on whatever you like
                //this is just a simple example 
                //return 1 if obj1 should be ordered first
                //return 0 if obj1 and obj2 are the same
                //return -1 if obj1 should be ordered after obj2
                return obj1.compareTo(obj2);
            }
        });

【讨论】:

    【解决方案3】:

    HashMap 数据结构用于允许在 O(1) 时间内访问其元素。

    因为它是一个数据容器,所以它的池或键可以随时间变化。这意味着您不能长期保证地图列表的顺序。

    在您的示例中,您匹配两个字符串并创建名为 SimpleBindings 的数据对。

    在您的简单示例中,您不应使用Map&lt;String,String&gt; 数据结构来表示Pair 数据。

    如果你的 SimpleBindings 真的由两个字符串组成,你必须做的只是在 SimpleBindings 类中实现一个Comparable,如下所示:

    class SimpleBinding implements  Comparable<SimpleBinding> {
    
        private final String key;
        private final String value;
    
        public SimpleBinding(String key, String value) {
            Objects.nonNull(key);
            Objects.nonNull(value);
            this.key = key;
            this.value = value;
    
        }
    
        @Override
        public int compareTo(SimpleBinding that) {
            return this.key.compareTo(that.key);
        }
    }
    

    而您只需使用Collections.sort(bindings ) 即可对结果进行排序。

    如果您无法访问该类,您应该使用像这样的Comparator 接口

    enum SimpleBindingComparator implements Comparator<SimpleBinding> {
         DEFUALT {
             @Override
             public int compare(SimpleBinding fist, SimpleBinding second) {
                 return fist.key.compareTo(second.key);
             }
         };
    

    然后你像这样对绑定进行排序Collections.sort(bindings ,SimpleBindingComparator.DEFAULT);

    但是,如果您的情况比这更复杂,并且您在列表中存储了一个 Map,您应该定义一个表示订单的逻辑。在您的情况下,订单必须由c1.getName() 维护可能会很遗憾

    一种选择是您不应该创建一个列表,而是创建一个列表Map&lt;String&gt;,List&lt;String&gt;&gt; 的映射,这就是所谓的多映射,其中单个键匹配多​​个值。请参阅番石榴的MultiMap,如果您希望对其进行排序,那么我建议阅读TreeMultiMap

    【讨论】:

    • 这会在Map 中创建密钥的副本并对副本进行排序。这既没有对Map 进行排序,也没有回答OP 关于对List&lt;Map&lt;&gt;&gt; 进行排序的问题。
    • 答案更多地指的是输出,而不是OP提供的代码。从这个角度来看是有效的。一般来说,您不能对地图进行排序。地图是数据容器。我所做的是创建并索引到地图。 (我没有复制数据只是引用),并用它来按要求的顺序显示结果。
    • 当然你可以对Map进行排序。您需要两件事,1) LinkedHashMap 和 2) Comparator。但这不是重点。 OP 说需要对 List&lt;Map&gt;&gt; 进行排序,而不是对 Maps in List 进行排序。
    • 没有。 LinkedHashMap 将按照它们放入列表的顺序解析您的项目。当您使用 TreeMap 结构时,将使用 Comparator。 OP 缺少的是多地图的概念。因为你不能指定地图的顺序,因为当你将它添加到它时,所有存储“订单”的容器都必须重建。但你有一些观点。我会更新我的答案。我希望这也能满足您的标准和 OP 问题。
    • 确实 - 使用 Comparator 对条目进行排序,然后将它们粘贴到 LinkedHashMap 中。排序地图,魔法。一个TreeMap具有不同的行为特征和不同的方法复杂度,它完全是一个不同的动物。虽然某种Multimap 可能是相关的,但关于 OP 为什么使用SimpleBindings 的更多信息很难说。
    猜你喜欢
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2019-05-29
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    相关资源
    最近更新 更多