我可以简单地使用TreeSet对ArrayList的ArrayList进行排序吗?

时间:2014-06-03 19:56:34

标签: java arraylist hashset treeset

===主要编辑(和次要编辑)===

我完全重写了我几天前提交的代码,因为它是基于其他两个代码不那么深思熟虑的代码,这是gitgo提出的一个非常不合适的想法。我没有足够的研究能力。

尽管如此,@ F. Böller非常友好地回答了关于我的原始代码的问题,并说我需要在此上下文中定义comparatorTreeSet<ArrayList<Integer>> hs = new TreeSet<>(comparator);

这是我对Google java treesort comparator所需的所有鼓励,并根据我在那里看到的内容进行了修订。这一点都不容易,我承认我仍然不太明白为什么下面的语法基本上都是我需要的,但是如果没有Googled链接上面的例子,我就永远不会想到它。

TreeSet<Leaf> theTreeSet = new TreeSet<>(new HowToCompareLeaves());

===次要编辑 - 以下行错误:

无论如何,下面的代码效果很好(根据每个“叶子”中的第一个元素排序)。

===以下行是正确的:

无论如何,下面的代码效果很好(对每个“叶子”中的所有元素进行排序和比较)。

===结束次要编辑===

但是,如果有人可以解释(之前从未使用过TreeSet的人)上面的行实际上做了什么,我会很感激。它似乎定义了一个新的实例,它定义为比较ar组成的数据项的方法......是吗?它是新TreeSet的构造函数,需要定义如何将新元素分类到自身中吗?

package treed;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetExample {

  public static final int NR = 4, NC = 3;

  public static void main(String a[])
  {
    ArrayList<Leaf> ar = new ArrayList<>(NR);

    for (int i = 0; i < NR; i++)
     ar.add(new Leaf());

    System.out.println("Pre-sort:");
    for(int i = 0; i < NR; i++)
      System.out.println(ar.get(i));

    TreeSet<Leaf> theTreeSet = new TreeSet<>(new HowToCompareLeaves());

    System.out.println("\nPost-sort:");
    for (int i = 0; i < NR; i++)
      theTreeSet.add(ar.get(i));

    for(Leaf e:theTreeSet)           
      System.out.println(e);
  }
}

class HowToCompareLeaves implements Comparator<Leaf>
{
  @Override 
  public int compare(Leaf e, Leaf f) 
  {
    if(e.row.get(0) > f.row.get(0)) return  1;
    if(e.row.get(0) < f.row.get(0)) return -1;
    return 0;
  }
}    

class Leaf
{
    ArrayList<Integer> row;  

    Leaf()
    {
      row = new ArrayList<>(TreeSetExample.NC);
      for (int i = 0; i < TreeSetExample.NC; i++)
        row.add((int)(Math.random()*89 + 10));
    }

  public String toString()
  {
    String s = "";
    for (int i = 0; i < TreeSetExample.NC; i++) {
      s += row.get(i) + "...";
    }
    return s;
  }
}

===编辑结束;休息是垃圾=======================

我正在关注一个关于ArrayList的ArrayList的一个新的未回答的问题,该问题需要进行非重复数据删除和排序。一个答案建议使用HashSet来删除重复项,但不会排序,因为下面的工作代码确认了。

import java.util.ArrayList;
import java.util.HashSet;

public class TwoDimArrayList {

  static           ArrayList<Integer> r;
  static ArrayList<ArrayList<Integer>> a2D = new ArrayList<>();

  public static void main(String[] args) {
    for (int i = 0; i < 5; i++) {
      r = new ArrayList<>();
      for (int j = 0; j < 3; j++)
        r.add((int)(Math.random() * 89 + 11));
      a2D.add(r);
    }
    for (int i = 0; i < a2D.size(); i++){
      for (int j = 0; j < a2D.get(i).size(); j++) 
        System.out.print(a2D.get(i).get(j) + "\t");
      System.out.println("...");
    }

    HashSet<ArrayList<Integer>> hs = new HashSet<>(a2D.size());

    for (int i = 0; i < a2D.size(); i++)
      hs.add(a2D.get(i));

    a2D.clear();

    for (int i = 0; i < hs.size(); i++)
      a2D.add((ArrayList<Integer>) hs.toArray()[i]);

    for (int i = 0; i < a2D.size(); i++){ 
      for (int j = 0; j < a2D.get(i).size(); j++)
        System.out.print(a2D.get(i).get(j) + "\t");
      System.out.println();
    }
  }
}

我尝试将HashSet更改为TreeSet,因为后者提供了排序:

TreeSet<ArrayList<Integer>> hs = new TreeSet<>(a2D.size());

这给出了错误:cannot infer arguments for TreeSet。所以我最终摆脱了它:

TreeSet<ArrayList<Integer>> hs = new TreeSet<>();

但我在这一行得到错误:

  hs.add(a2D.get(i));

Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Comparable

对此有一些简单的解决方法吗?或者希望TreeSet进行排序本身就是错误的? (我是新手,以防有人想知道......)

2 个答案:

答案 0 :(得分:7)

TreeSet不知道如何对ArrayLists进行排序,因为列表没有自然排序。它应该将列表与值的最小值,列表的平均值或其他值进行比较吗? 要使TreeSet了解要排序的内容,必须在构造函数中添加一个比较器:

TreeSet<ArrayList<Integer>> hs = new TreeSet<>(comparator);

比较器必须实现接口Comparator<ArrayList>。在这里您可以定义如何订购ArrayList。 如果你不添加一个比较器,TreeSet会隐式地期望ArrayList实现Comparable-Interface,而它不会这样做。

答案 1 :(得分:1)

如果你想对List<Integer>的列表进行排序,那么你必须为此自己编写逻辑。 Java无法自动推断出这种排序。

TreeSet使用元素的自然顺序来保持整个Set的排序。但是在你的情况下,这种自然顺序是未定义的,因此是ClassCastException