Могу ли я отсортировать ArrayList из ArrayList просто с помощью TreeSet?

=== ОСНОВНОЕ РЕДАКТИРОВАНИЕ (и незначительное) ===

Я полностью переписал код, который я представил пару дней назад, так как он основан на двух не очень хорошо продуманных блоках кода, что является очень неуместной идеей из гитго. Мое плохо, потому что я не смог исследовать достаточно.

Тем не менее, @F. Беллер был достаточно любезен, чтобы ответить на вопрос о моем исходном коде и сказал, что мне нужно определить comparator в данном контексте: TreeSet<ArrayList<Integer>> hs = new TreeSet<>(comparator);,

Это было всем ободрением, которое мне было нужно для компилятора Google java treeort, и основал мой пересмотр на том, что я там увидел. Это было совсем непросто, и я признаюсь, что до сих пор не совсем понимаю, ПОЧЕМУ приведенный ниже синтаксис оказался в основном всем, что мне было нужно, но я бы никогда не придумал его без примера по ссылке Googled выше.

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

=== незначительное РЕДАКТИРОВАНИЕ - СЛЕДУЮЩАЯ ЛИНИЯ НЕПРАВИЛЬНО:

В любом случае, приведенный ниже код прекрасно работает (сортирует по 1-му элементу в каждом "листе").

=== СЛЕДУЮЩАЯ ЛИНИЯ ПРАВИЛЬНО:

В любом случае, приведенный ниже код прекрасно работает (сортирует и сравнивает ВСЕ элементы в каждом "листе").

=== конец незначительного редактирования ===

Тем не менее, я был бы признателен, если бы кто-то мог объяснить (кому-то, кто никогда не использовал 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 ответа

Решение

TreeSet не знает, как сортировать ArrayLists, потому что нет естественного упорядочения списков. Должен ли он сравнивать списки по минимуму значений, среднему значению списка или чему-то еще? Чтобы TreeSet понял, что вы хотите отсортировать, вы должны добавить компаратор в конструктор:

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

Компаратор должен реализовать интерфейс Comparator<ArrayList>, Здесь вы можете определить, как заказать ArrayList. Если вы не добавите компаратор, TreeSet неявно ожидает, что ArrayList реализует Comparable-Interface, чего он не делает.

Если вы хотите отсортировать список List<Integer>Чем вам самим придется написать логику для этого. Java не может автоматически определить этот порядок.

TreeSet использует естественный порядок вашего элемента для сортировки всего набора. В вашем случае, однако, этот естественный порядок не определен, следовательно, ClassCastException,

Другие вопросы по тегам