【问题标题】:How can I sort an ArrayList<ArrayList<String>>?如何对 ArrayList<ArrayList<String>> 进行排序?
【发布时间】:2025-11-21 17:00:02
【问题描述】:

所以我正在为我正在为学校工作的程序开发广度优先搜索功能,当我通过给定节点的传出边缘时,凭借我如何通过我的可能边缘,它看起来像这样:

[[A, 1], [D, 1], [C, 2], [D, 2]]

但我真正想要的是:

[[A, 1], [C, 2], [D, 1], [D, 2]]

其中第一个索引是边缘指向的节点的名称,第二个索引是边缘的标签。本质上,我想按字母顺序遍历这些边缘,首先按节点名称,然后按标签名称,但我不知道该怎么做,因为 Collections.sort() 不适用于 2D ArrayList。关于排序的好方法的任何指针/想法?谢谢大家!

编辑:我使用的是 JRE 1.7,而不是 1.8

【问题讨论】:

  • [[A, 1], [D, 1], [C, 2], [D, 2]] 不是ArrayList&lt;ArrayList&lt;String&gt;&gt; 的有效示例您可以使用.stream().sorted() 按自然顺序排序,甚至定义自定义Comparator
  • 你可以使用 HashMap 而不是 ArrayList...
  • RoiEX,不能使用 HashMap,因为他可以有一个具有不同值的 Key,或者必须是一个 HashMap ...这使得一些简单的结构变得相当复杂。

标签: java sorting arraylist


【解决方案1】:

这是完整的工作代码。 在 java SDK8 中使用 lambda 表达式。

如您所见,我添加了一个简单的类和一个比较器。这既简单又强大。

package com.rizze.test.labs.sof;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.junit.Test;

public class SOF {    

    public static class Link {
        public String name;
        public int id;

        public static Link build(String n, int i){
            Link l = new Link();
            l.name = n;
            l.id=i;
            return l;
        }

        public String toString(){
            return String.format("[%s , %d]", name,id);
        }           
    }       

    @Test
    public void test() {

        List<Link> links = new ArrayList<Link>();

        //SSETUP [[A, 1], [C, 2], [D, 1], [D, 2]]
        links.add(Link.build("D", 1));
        links.add(Link.build("A", 1));
        links.add(Link.build("D", 2));
        links.add(Link.build("C", 2));


        Collections.sort(links, new Comparator<Link>() {    
            @Override
            public int compare(Link p1, Link p2) {
                int ret = p1.name.compareTo(p2.name);
                if(ret == 0) {
                    ret= p1.id - p2.id;
                }
                return ret;             
            }               
        });
        System.out.println(links);          
    }    
}

//控制台输出

Before : [[D , 1], [A , 1], [D , 2], [C , 2]]
Sorted: [[A , 1], [C , 2], [D , 1], [D , 2]]

//GIST 链接 https://gist.github.com/jeorfevre/cbcd7dac5d7fabde6a16db83bdfb7ef5

【讨论】:

    【解决方案2】:

    @jeorfevre 答案完全可以。您没有提到 Java 版本,但我会使用静态 Comparator 方法。

    解决方案将是声明性的,并以简洁的方式为您提供更多控制和清晰:

    public class Test {
        public static class Edge {
            private String name;
            private int label;
            public Edge(String name, int id) {
                this.name = name;
                this.label = id;
            }
            public String toString() {
                return String.format("[%s , %d]", name, label);
            } 
            public String getName() { return name; } 
            public int getLabel() { return label; }
        }
    
    
        public static void main(String[] args) {
            List<Edge> edges = new ArrayList<>();
            edges.add(new Edge("D", 1));
            edges.add(new Edge("A", 1));
            edges.add(new Edge("D", 2));
            edges.add(new Edge("C", 2));
    
            Comparator<Edge> comparator = Comparator
                    .comparing(Edge::getName)
                    .thenComparing(Edge::getLabel);
    
            edges.sort(comparator);
    
            System.out.println(edges);
        }
    }
    

    如果你想颠倒顺序:

                Comparator<Edge> comparator = Comparator
                    .comparing(Edge::getName)
                    .thenComparing(Edge::getLabel)
                    .reversed();
    

    给你:

    [[D , 2], [D , 1], [C , 2], [A , 1]]
    

                Comparator<Edge> comparator = Comparator
                    .comparing(Edge::getName)
                    .reversed()
                    .thenComparing(Edge::getLabel);
    

    输出是: [[D, 1], [D, 2], [C, 2], [A, 1]]

    【讨论】:

    • 这看起来很棒!这几乎正​​是我正在考虑实现的(Edge 类),它让我对如何管理我的边缘有了更多的看法。我的下一个问题是,由于我不是在 Edge 类中使用这些边缘,而是在完全不同的类中使用这些边缘,所以我会将比较器放在哪里?它会进入我目前正在使用的任何功能吗?抱歉,我对 Java 比较陌生,对比较器也很陌生。
    • 另外,我对命令 Edge::getName 和 Edge::getLabel 有疑问,因为对于这个作业,我的教授希望我们使用 JRE 1.7,而不是 1.8。还有其他方法可以使用 JRE 1.7 来实现吗?
    最近更新 更多