java sort set,Java集合框架之Set接口、实现类、排序

  • Post author:
  • Post category:java

1. Set接口与实现类

特点:

1)无序、无下标、元素不可重复(当插入新元素时,如果新元素与已有元素进行equals比较,结果为true时,则拒绝新元素插入)

2)set接口并没有提供自己独有的方法,均是继承Collection的方法

Set 注重独一无二的性质,该体系集合用于存储无序(存入和取出的顺序不一定相同)元素,值不能重复。对象的相等性本质是对象 hashCode 值(java 是依据对象的内存地址计算出的此序号)判断的,如果想要让两个不同的对象视为相等的,就必须覆盖 Object 的 hashCode 方法和 equals 方法。

元素不重复的基本逻辑判断示意图:

a7dc1a5a0cc9

重写hashCode和equals方法

包装类型,重写hashCode就很简单:

class Student{

String name;

Integer age;

String sex;

Double score;

// …

@Override

public int hashCode() {

return (this.name.hashCode() + this.sex.hashCode() + this.age.hashCode() + this.score.hashCode());

}

}

Set接口的实现类:HashSet、LinkedHashSet、TreeSet

① HashSet类(基于HashCode-无序)

特点:

基于HashCode实现元素不重复 – 无序

当存入元素的哈希码相同时,会调用equals确认,结果为true,则拒绝后者加入

无参构建初始容量为16(负载因子0.75,即+75%容量扩容)

底层使用的HashMap类,即将所有需要存储的值,通过HashMap去重存入

先判断hashCode是否相同,再==比较地址是否相同,再equals内容是否相同

import java.util.HashSet;

import java.util.Set;

public class TestHashSet3 {

public static void main(String[] args) {

Student s1 = new Student(“tom”, 20, “male”, 99.0); // 0x0000 1111

Student s2 = new Student(“jack”, 23, “male”, 88.0);

Student s3 = new Student(“mark”, 22, “male”, 95.0);

Student s4 = new Student(“anna”, 21, “female”, 93.0);

Student s5 = new Student(“tom”, 20, “male”, 99.0); // 0x0000 2222

Set students = new HashSet(); // 快速导包:Ctrl+Shift+O

students.add(s1); // 0x0000 1111

students.add(s2);

students.add(s3);

students.add(s4);

students.add(s1); // 0x0000 1111, add失败,去掉了重复:equals—>Object类提供的(this==obj)判断

students.add(s5); // 0x0000 2222(内容相同,地址不同)也需要去重

for (Student student : students) {

System.out.println(student.toString());

}

/*

* 注意:HashSet没有必要在每次插入一个新值时对数据都去一一比较

* 注意:HashSet调用equals方法进行比较,是具有前提的(两个对象的哈希码相同)

*/

System.out.println(s1.equals(s5));

}

}

class Student{

String name;

Integer age;

String sex;

Double score;

public Student() {}

public Student(String name, Integer age, String sex, Double score) {

super();

this.name = name;

this.age = age;

this.sex = sex;

this.score = score;

}

@Override

public String toString() {

return “Student [name=” + name + “, age=” + age + “, sex=” + sex + “, score=” + score + “]”;

}

@Override

public boolean equals(Object obj) {

System.out.println(“Student’s equals() method executed…”);

if (this == obj) { return true; }

if (null == obj) { return false; }

if (this.getClass() != obj.getClass()) { return false; }

Student s = (Student)obj;

if (this.toString().equals(s.toString())) {

return true;

}

return false;

}

@Override

public int hashCode() {

return (this.name.hashCode() + this.sex.hashCode() + this.age.hashCode() + this.score.hashCode());

}

}

② LinkedHashSet类(记录插入顺序)

特点:

继承自HashSet,又基于LinkedHashMap来实现的

底层使用LinkedHashMap(链表结构)存储,节点形式独立存储数据,并可以指向下一个节点,通过顺序访问节点,可保留元素的插入顺序 – 插入顺序

所有方法与HashSet相同,用法也一模一样

import java.util.LinkedHashSet;

public class TestLinkedHashSet {

public static void main(String[] args) {

// 底层使用LinkedHashMap(链表结构)存储,节点形式完成单独数据的保存

// 并可以指向下一个节点,通过顺序访问节点,可保留元素的插入顺序

LinkedHashSet set = new LinkedHashSet();

set.add(“aa”);

set.add(“bb”);

set.add(“cc”);

set.add(“dd”);

set.add(“ee”);

for (String s : set) {

System.out.print(s + ” “);

}

System.out.println();

LinkedHashSet lhs = new LinkedHashSet();

lhs.add(11);

lhs.add(99);

lhs.add(66);

lhs.add(33);

lhs.add(55);

lhs.add(44);

for (Integer i : lhs) {

System.out.print(i + ” “);

}

}

}

③ TreeSet类(二叉树-自动排序)

特点:

基于排列顺序实现元素不重复 – 自动排序

实现了SortedSet接口,对所有插入集合的元素自动排序

元素对象的类型必须实现Comparable接口,指定排序规则(Integer/String类默认实现),通过重写CompareTo方法才能使用,以确定是否为重复元素

import java.util.TreeSet;

public class TestTreeSet2 {

public static void main(String[] args) {

TreeSet stus = new TreeSet();

stus.add(new Student(“tom”, 20, “male”, 80.0));

stus.add(new Student(“jak”, 20, “male”, 90.0));

stus.add(new Student(“vae”, 20, “male”, 100.0));

stus.add(new Student(“com”, 20, “male”, 60.0));

for (Student student : stus) {

System.out.println(student.toString());

}

}

}

class Student implements Comparable{

String name;

Integer age;

String sex;

Double score;

public Student() {

super();

}

public Student(String name, Integer age, String sex, Double score) {

super();

this.name = name;

this.age = age;

this.sex = sex;

this.score = score;

}

@Override

public int compareTo(Student o) {

//主要排序列

if (this.score < o.score) {

return -1;

} else if (this.score > o.score){

return 1;

} else {

//次要排序列(排序的属性中可能是个多属性的对象)

if (this.age < o.age) {

return -1;

} else if (this.age > o.age) {

return 1;

}

}

return 0;

}

@Override

public String toString() {

return “Student [name=” + name + “, age=” + age + “, sex=” + sex + “, score=” + score + “]”;

}

}

2. HashSet排序的两种方法

1)遍历加入到List中使用Collections.sort(list)排序;

2)使用TreeSet的构造创建一个TreeSet对象实现自动排序;

import java.util.ArrayList;

import java.util.Collections;

import java.util.HashSet;

import java.util.List;

import java.util.TreeSet;

public class TestHashSetSort {

public static void main(String[] args) {

/* 对HashSet排序的两种办法验证 */

HashSet numSet = new HashSet();

numSet.add(55);

numSet.add(11);

numSet.add(66);

numSet.add(88);

numSet.add(33);

System.out.println(numSet); // [33, 66, 55, 88, 11]

System.out.println(“————————“);

sortByTreeSet(numSet); // [11, 33, 55, 66, 88]

System.out.println(“————————“);

sortByList(numSet); // [11, 33, 55, 66, 88]

}

// 装进TreeSet里,自动排序

public static void sortByTreeSet(HashSet set) {

TreeSet numTree = new TreeSet(set);

System.out.println(numTree);

}

// 装进ArrayList里,通过sort排序

public static void sortByList(HashSet set) {

List numList = new ArrayList();

for (Integer i : set) {

numList.add(i);

}

Collections.sort(numList);

System.out.println(numList);

}

}