如何对 HashSet 进行排序?

对于列表,我们使用 Collections.sort(List)方法?

347365 次浏览

您可以使用 树集代替。

使用 java.util.TreeSet作为实际的对象。当您在这个集合上迭代时,这些值将按照定义良好的顺序返回。

如果您使用 java.util.HashSet,那么顺序取决于一个内部散列函数,这几乎可以肯定不是字典(基于内容)。

HashSet 不保证其元素的任何顺序。如果需要这种保证,可以考虑使用 TreeSet 来保存元素。

但是,如果您只需要为这个事件对元素进行排序,那么只需临时创建一个 List 并对以下内容进行排序:

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


...


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

将所有对象添加到 TreeSet,您将得到一个排序集。

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]

更新

您还可以使用以 HashSet作为参数的 TreeSet构造函数。

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


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

谢谢@Mounika 的更新。

这个简单的命令帮了我大忙:

myHashSet.toList.sorted

我在 print 语句中使用了它,所以如果您需要实际持久化排序,您可能需要使用 TreeSet 或在此线程上提出的其他结构。

哈希集中的元素无法排序。无论何时将元素放入 HashSet,它都会扰乱整个集合的顺序。这是为了表演而特意设计的。当您不关心顺序时,HashSet 将是最有效的频繁插入和查询集。

TreeSet 是您可以使用的替代方案。当您在树集合上迭代时,您将自动获得已排序的元素。 但是它会在每次插入元素时调整树以保持排序。

也许,您正在尝试做的就是排序一次。在这种情况下,TreeSet 不是最有效的选项,因为它需要始终确定新添加元素的位置。只有在需要经常排序时才使用 TreeSet。

如果只需要排序一次,请使用 ArrayList。创建一个新列表并添加所有元素,然后对其排序一次。如果您只想保留唯一的元素(删除所有重复的元素) ,那么将列表放入 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

现在,您已经得到了一个已排序的集合,如果您希望它以列表形式出现,那么可以将其转换为列表。

你可以这样做:

方法一:

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

方法二:

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

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

您可以按照其他答案中提到的那样使用 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
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);
}
}
}

输入式普拉卡什夏尔马苹果香蕉

输出-苹果香蕉普拉卡什切片

也可以使用番石榴库

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

Java8的排序方法是:

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 =捕获它

我们无法确定 HashSet 的元素是否会自动排序。但是我们可以通过转换为 TreeSet 或者任何类似 ArrayList 或 LinkedList 的 List 来对它们进行排序。

// 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");

您可以使用 Java8收集器和 TreeSet

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

在我看来,LazerBanana 的答案应该是排名最高的答案并被接受,因为所有其他指向 java.util.TreeSet的答案(或者首先转换为列表,然后在转换后的列表中调用 Collections.sort(...))都懒得问 OP 你的 HashSet有什么样的对象,也就是说,如果这些元素有预定义的 自然秩序或者没有 & 这不是可选的问题,而是一个强制性的问题。

如果元素类型没有实现 Comparable接口,或者没有显式地将 Comparator传递给 TreeSet构造函数,那么就不能开始将 HashSet元素放到 TreeSet中。

来自 TreeSet JavaDoc,

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

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

话虽如此,其他的顾虑还有,

  1. 分类表现
  2. 内存脚印(保留原始集,并创建新的排序集,每次排序完成或希望排序的地方等集)

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

由于原始集合已经包含只有 独一无二元素和约束也是由排序集维护,所以原始集合需要从内存中清除,因为数据是重复的。

你可以像这样把它包在一个 TreeSet 里:

Set mySet = new HashSet();
mySet.add(4);
mySet.add(5);
mySet.add(3);
mySet.add(1);
System.out.println("mySet items "+ mySet);


TreeSet treeSet = new TreeSet(mySet);
System.out.println("treeSet items "+ treeSet);

产出:
MySet item [1,3,4,5]
TreeSet item [1,3,4,5]

Set mySet = new HashSet();
mySet.add("five");
mySet.add("elf");
mySet.add("four");
mySet.add("six");
mySet.add("two");
System.out.println("mySet items "+ mySet);


TreeSet treeSet = new TreeSet(mySet);
System.out.println("treeSet items "+ treeSet);

产出:
MySet 条目[6,4,5,2,小精灵]
树设置项目[精灵,五,四,六,二]

这个方法的要求是 set/list 的对象应该是可比较的(实现可比较接口)

如果你想最终 Collection的形式是 Set,如果你想定义自己的 natural order而不是 TreeSet,那么-

  1. HashSet转换为 List
  2. 自定义使用 ComparatorList进行排序
  3. List转换回 LinkedHashSet以维持秩序
  4. 显示 LinkedHashSet

    示例程序-
package demo31;


import java.util.*;
public class App26 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
addElements(set);
List<String> list = new LinkedList<>();
list = convertToList(set);
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
int flag = s2.length() - s1.length();
if(flag != 0) {
return flag;
} else {
return -s1.compareTo(s2);
}
}
});
Set<String> set2 = new LinkedHashSet<>();
set2 = convertToSet(list);
displayElements(set2);
}
public static void addElements(Set<String> set) {
set.add("Hippopotamus");
set.add("Rhinocerous");
set.add("Zebra");
set.add("Tiger");
set.add("Giraffe");
set.add("Cheetah");
set.add("Wolf");
set.add("Fox");
set.add("Dog");
set.add("Cat");
}
public static List<String> convertToList(Set<String> set) {
List<String> list = new LinkedList<>();
for(String element: set) {
list.add(element);
}
return list;
}
public static Set<String> convertToSet(List<String> list) {
Set<String> set = new LinkedHashSet<>();
for(String element: list) {
set.add(element);
}
return set;
}
public static void displayElements(Set<String> set) {
System.out.println(set);
}
}

输出-

[Hippopotamus, Rhinocerous, Giraffe, Cheetah, Zebra, Tiger, Wolf, Fox, Dog, Cat]

在这里,集合被排序为-

String长度的降序
String字母层次结构的二阶递减顺序 < br >

基于@LazerBanana 给出的答案,我将用我自己的例子来说明一个按照对象的 Id 排序的集合:

Set<Clazz> yourSet = [...];


yourSet.stream().sorted(new Comparator<Clazz>() {
@Override
public int compare(Clazz o1, Clazz o2) {
return o1.getId().compareTo(o2.getId());
}
}).collect(Collectors.toList()); // Returns the sorted List (using toSet() wont work)

为了以防万一你不想使用 TreeSet,你可以尝试使用 java 流来获得简洁的代码。

set = set.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));

下面是我的示例代码,它已经通过在注释中指向代码得到了回答,我仍然在分享,因为它包含了完整的代码

package Collections;


import java.util.*;


public class TestSet {


public static void main(String[] args) {


Set<String> objset = new HashSet<>();


objset.add("test");
objset.add("abc");
objset.add("abc");
objset.add("mas");
objset.add("vas");


Iterator itset = objset.iterator();
while(itset.hasNext())
{
System.out.println(itset.next());
}


TreeSet<String> treeobj = new TreeSet(objset);
System.out.println(treeobj);




}
}

TreeSet treeobj = new TreeSet (objecset) ; 这里我们调用 TreeSet 构造函数,它将调用 addAll 方法来添加对象。

请参阅下面的代码,它来自 TreeSet 类,

public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
}

HashSet转换为 List,然后使用 Collection.sort()对其进行排序

List<String> list = new ArrayList<String>(hset);
Collections.sort(List)