【问题标题】:JAVA: Sort ArrayList<ArrayList<Integer>> on multiple columnsJAVA:对多列排序 ArrayList<ArrayList<Integer>>
【发布时间】:2012-09-17 21:16:21
【问题描述】:

首先,我在发帖之前做了功课搜索。与那里发布的问题相比,我的要求似乎略有不同。

我有一个像ArrayList&lt;ArrayList&lt;Integer&gt;&gt; 这样的矩阵,格式如下

| id1 | id2 | score |
|-----|-----|-------|
| 1   | 3   | 95%   |
| 1   | 2   | 100%  |
| 1   | 4   | 85%   |
| 1   | 5   | 95%   |
| 2   | 10  | 80%   |
| 2   | 15  | 99%   |

我想按列对矩阵进行排序(首先使用分数,然后使用 id1)。我已经以排序方式获得了 id1。这意味着我还需要首先使用 score 对具有相同 id1 的所有记录进行排序,然后使用 id2 对所有记录进行排序。这样做的原因是在每个 id1 中创建 id2 的排名。上述示例的结果将是:

| q_id | d_id | rank | score |
|------|------|------|-------|
| 1    | 2    | 1    | 100%  |
| 1    | 3    | 2    | 95%   |
| 1    | 5    | 3    | 95%   |
| 1    | 4    | 4    | 85%   |
| 2    | 15   | 1    | 99%   |
| 2    | 10   | 2    | 80%   |

如何在 Java 中使用一些内置的集合方法来实现这一点?

【问题讨论】:

  • 为什么不使用Guava Collections 中的Table 类型?
  • 你能详细说明你想要达到的目标吗?
  • 您想要桶排序/基数排序的变体。第一个桶是 id1,第二个桶是 id2。

标签: java sorting matrix arraylist multiple-columns


【解决方案1】:

创建一个包含每个 ArrayList 行的所有列/字段的对象。然后使用 Comparator 接口并使用 Collections.sort()。

您可以查看http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#sort%28java.util.List,%20java.util.Comparator%29

【讨论】:

  • 你能详细说明一下吗?
  • 我可以使用一列进行排序。每当我使用第二列进行排序时,它不会弄乱第一个排序性质吗?或者它是否足够聪明,可以让第一个排序结果以其形式出现,然后使用第二个键进行相应排序?
  • Jim 已经回答了我想说的话 :)
【解决方案2】:

适当的 OO 解决方案是将其声明为

class Bucket {
    int val1;
    int val2;
    int percent;
}

List<Bucket> myList = ...

并提供一个Comparator,以您想要的方式对元素进行排序

【讨论】:

    【解决方案3】:

    我不确定您所描述的实际上是一个矩阵。在我看来,它就像一组三胞胎。

    考虑为矩阵的每一“行”创建一个包装类:

    class Triplet implements Comparable<Triplet> {
        private int id1;
        private int id2;
        private int score;
    
        // getters / setters here
    
        @Override
        int compareTo(Triplet that) {
            // if I understood correctly, you want to sort by score, then id1, then id2.
            int result = this.score - that.getScore();
            if (result == 0) {
                result = this.id1 - that.getId1();
                if (result == 0) {
                    result = this.id2 - that.getId2();
                }
            }
    
            return result;
        }
    }
    

    然后将您的“矩阵”表示为ArrayList&lt;Triplet&gt;,然后像往常一样进行排序。

    【讨论】:

      【解决方案4】:

      首先,您最好将数据保存在普通旧 Java 对象 (POJO) 中,而不是整数列表列表中。

      从您的示例中,您的数据似乎包含三个元素:两个 id 和一个分数。 POJO 可能是这样的:

      public class Record() {
          private int id1;
          private int id2;
          private double score; // percent, so double from 0.0 to 1.0
      
          public Record(int id1, int id2, double score) {
              this.id1=id1;
              this.id2=id2;
              this.score=score;
          }
          // getters and setters
      }
      

      那么,您只需拥有一个List&lt;Record&gt;,而不是复杂的子列表。

      根据我对您的问题的了解,您想先按 id1 排序,然后按 id2 排序。是对的吗?这看起来需要radix sort(链接到维基百科)。

      伪代码是这样的:

      1. 循环遍历每条记录,并按id1 将它们分类到“桶”中。每个“桶”可以是一个List&lt;Record&gt;,并且应该包含所有具有相同id1 的Record 对象,没有特定的顺序。
      2. 遍历每个存储桶并按id2 排序。
      3. 将所有存储桶重新组合在一起,保持顺序。

      您需要使用public int compareId1(Record other)public int compareId2(Record other) 等方法更新Record 对象,以便高效、干净地实现这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-22
        • 1970-01-01
        • 2015-07-05
        • 1970-01-01
        相关资源
        最近更新 更多