如何对HashSet进行排序?

问题描述 投票:73回答:14

对于列表,我们使用Collections.sort(List)方法。如果我们想要对HashSet进行排序怎么办?

java sorting collections set hashset
14个回答
97
投票

HashSet不保证其元素的任何顺序。如果您需要此保证,请考虑使用TreeSet来保存元素。

但是,如果您只需要为这一次出现排序的元素,那么只需临时创建一个List并对其进行排序:

Set<?> yourHashSet = new HashSet<>();

...

List<?> sortedList = new ArrayList<>(yourHashSet);
Collections.sort(sortedList);

1
投票
1. Add all set element in list -> al.addAll(s);
2. Sort all the elements in list using -> Collections.sort(al);


 public class SortSetProblem {
 public static void main(String[] args) {
    ArrayList<String> al = new ArrayList();
    Set<String> s = new HashSet<>();
    s.add("ved");
    s.add("prakash");
    s.add("sharma");
    s.add("apple");
    s.add("ved");
    s.add("banana");
    System.out.println("Before Sorting");
    for (String s1 : s) {
        System.out.print("  " + s1);
    }

    System.out.println("After Sorting");
    al.addAll(s);
    Collections.sort(al);
    for (String set : al) {
        System.out.print(" " + set);
    }
  }
 }

输入 - Ved Prakash Sharma制作Apple Ved

输出 - Apple Banana Prakash Sharma Ved


0
投票

您可以通过以下方式执行此操作:

方法1:

  1. 创建一个列表并将所有hashset值存储到其中
  2. 使用Collections.sort()对列表进行排序
  3. 将列表存储回LinkedHashSet,因为它保留了插入顺序

方法2:

  • 创建一个treeSet并将所有值存储到其中。

方法2是更优选的,因为另一种方法消耗大量时间来在哈希集和列表之间来回传输数据。


0
投票

我们无法确定HashSet的元素会自动排序。但我们可以通过转换为TreeSet或任何List(如ArrayList或LinkedList等)对它们进行排序。

// Create a TreeSet object of class E
TreeSet<E> ts = new TreeSet<E> ();

// Convert your HashSet into TreeSet
ts.addAll(yourHashSet);

System.out.println(ts.toString() + "\t Sorted Automatically");

0
投票

您可以使用guava库

Set<String> sortedSet = FluentIterable.from(myHashSet).toSortedSet(new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        // descending order of relevance
        //required code
    }
});


-4
投票

这个简单的命令对我有用:

myHashSet.toList.sorted

我在print语句中使用了这个,所以如果你需要实际保持顺序,你可能需要使用TreeSets或这个线程上提出的其他结构。


56
投票

将所有对象添加到TreeSet,您将获得一个已排序的Set。以下是一个原始示例。

HashSet myHashSet = new HashSet();
myHashSet.add(1);
myHashSet.add(23);
myHashSet.add(45);
myHashSet.add(12);

TreeSet myTreeSet = new TreeSet();
myTreeSet.addAll(myHashSet);
System.out.println(myTreeSet); // Prints [1, 12, 23, 45]

14
投票

使用java.util.TreeSet作为实际对象。迭代此集合时,值将以明确定义的顺序返回。

如果你使用java.util.HashSet,那么顺序取决于内部哈希函数,这几乎肯定不是词典(基于内容)。


12
投票

您可以使用TreeSet代替。


11
投票

Java 8的排序方式是:

fooHashSet.stream()
  .sorted(Comparator.comparing(Foo::getSize)) //comparator - how you want to sort it
  .collect(Collectors.toList()); //collector - what you want to collect it to

* Foo::getSize这是一个如何按大小自然地对YourItem的HashSet进行排序的示例。

* Collectors.toList()将收集排序到List中的结果,您将需要使用List<Foo> sortedListOfFoo =捕获它


5
投票

您可以使用Java 8收集器和TreeSet

list.stream().collect(Collectors.toCollection(TreeSet::new))


4
投票

您可以使用其他答案中提到的TreeSet。

这里有一些关于如何使用它的详细说明:

TreeSet<String> ts = new TreeSet<String>();
ts.add("b1");
ts.add("b3");
ts.add("b2");
ts.add("a1");
ts.add("a2");
System.out.println(ts);
for (String s: ts)
    System.out.println(s);

输出:

[a1, a2, a3, a4, a5]
a1
a2
b1
b2
b3

2
投票

HashSet中的元素无法排序。每当你将元素放入HashSet时,它都会搞乱整个桶。它的好处是性能效率。

每次插入元素时,TreeSet都会自动对所有元素进行排序。

也许,你要做的只是排序一次。在这种情况下,TreeSet不是最佳选择,因为它需要始终确定新添加元素的放置。

最有效的解决方案是使用ArrayList。创建一个新列表并添加所有元素,然后对其进行一次排序。如果您只想保留唯一元素(删除所有重复项,如set do,则将列表放入LinkedHashSet,它将保留您已排序的顺序)

List<Integer> list = new ArrayList<>();
list.add(6);
list.add(4);
list.add(4);
list.add(5);
Collections.sort(list);
Set<Integer> unique = new LinkedHashSet<>(list); // 4 5 6
// The above line is not copying the objects! It only copies references.

现在,如果您希望它以列表形式存在,那么您已经获得了一个排序集,然后将其转换为列表。


2
投票

在我的拙见中,LazerBanana的答案应该是最受欢迎的答案并被接受,因为所有其他答案指向java.util.TreeSet(或首先转换为列表然后在转换列表上调用Collections.sort(...))没有打扰要求OP作为什么样的对象你的HashSet即如果这些元素具有预定义的自然顺序,那么这不是可选问题,而是强制性问题。

如果元素类型尚未实现HashSet接口或者您没有明确地将TreeSet传递给Comparable构造函数,那么您就无法进入并开始将Comparator元素放入TreeSet

来自TreeSet JavaDoc,

构造一个新的空树集,根据其元素的自然顺序进行排序。插入到集合中的所有元素都必须实现Comparable接口。此外,所有这些元素必须是可相互比较的:e1.compareTo(e2)不得对集合中的任何元素e1和e2抛出ClassCastException。如果用户尝试向违反此约束的集合添加元素(例如,用户尝试将字符串元素添加到其元素为整数的集合中),则add调用将抛出ClassCastException。

这就是为什么只有所有基于Java8流的答案 - 你在现场定义你的比较器 - 才有意义,因为在POJO中实现可比性是可选的。程序员在需要时定义比较器。试图收集到TreeSet而不问这个基本问题也是不正确的(忍者的回答)。假设对象类型为StringInteger也不正确。

话虽如此,其他问题如,

  1. 排序性能
  2. 记忆足印(每次分类完成后保留原始设定并创建新的分类组或希望对该组进行分类等)

也应该是其他相关点。只是指向API不应该只是意图。

由于原始集已经只包含唯一元素,并且约束也由排序集维护,因此需要从内存中清除原始集,因为数据是重复的。

© www.soinside.com 2019 - 2024. All rights reserved.