目次
2.2HashSetはどのようにして要素の一意性を保証しますか
4.1 TreeSetは、整数型の要素とトラバースを格納します
4.2 TreeSetは、カスタムオブジェクトとトラバースを格納します
1.Setインターフェースの概要
繰り返される要素を含まないコレクション。
2.HashSetコレクション
2.1概要
- セットの反復順序は保証されません
- 特に、シーケンスが永遠に続くことを保証するものではありません
2.2HashSetはどのようにして要素の一意性を保証しますか
- HashSetコレクションの最下層は、ハッシュテーブル構造に依存します
- ハッシュテーブル構造の最下層は、hashcode()メソッドとequals()メソッドに依存しています
2.3HashSetケース
2.3.1 HashSetは、文字列とトラバースを格納します
HashSetは文字列を格納してトラバースします。また、Stringクラスはhashcode()メソッドとequals()メソッドを書き換えるため、出力結果要素は一意です。したがって、同じ内容の文字列を削除して、要素の一意性を確保できます。
基礎となる主成分分析は次のとおりです。
- まず、hashcode()の値が同じかどうかを比較します
- それらが同じである場合は、equals()メソッドを引き続き使用します
- trueを返し、要素が重複していることを示します。追加しないでください
- falseを返し、要素が繰り返されていないことを示します。コレクションに追加するだけです。
- それらが異なる場合は、要素をコレクションに直接追加します
// 创建集合对象
HashSet<String> hs = new HashSet<String>();
// 添加元素
hs.add("Python");
hs.add("Fiddler");
hs.add("Selenium");
hs.add("Fiddler");
// 增强for遍历集合
for (String str : hs) {
System.out.println(str);
}
演算結果:
Selenium
Fiddler
Python
2.3.2 HashSetは、カスタムオブジェクトとトラバースを格納します
- 学生(名前、年齢)
- 要件:2つのオブジェクトのメンバー変数の値が同じである場合、それらは同じ要素です。
Student.javaのコードは次のとおりです。
package com.hw.set;
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
テストコードは次のとおりです。
// 创建集合对象
HashSet<Student> hs = new HashSet<Student>();
// 创建学生对象
Student s1 = new Student("西施", 20);
Student s2 = new Student("貂蝉", 22);
Student s3 = new Student("昭君", 18);
Student s4 = new Student("貂蝉", 22);
// 把学生对象添加到集合中
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
// 增强for遍历集合
for (Student stu : hs) {
System.out.println(stu.getName() + "---" + stu.getAge());
}
操作の結果は次のとおりです。
西施---20
昭君---18
貂蝉---22
貂蝉---22
この場合、2つのオブジェクトのメンバー変数の値が同じである場合、それらは同じ要素である必要があります。実際には、3つの学生オブジェクトを出力する必要がありますが、4つの学生オブジェクトすべてが出力されます。その理由は、Studentクラスがhashcode()メソッドとequals()メソッドをオーバーライドしないためです。デフォルトではObjectクラスの2つのメソッドが使用されます。現時点では、studentのハッシュ値が異なるため、4つすべてが異なります。学生オブジェクトが出力されます。
解決策:Studentクラスのhashcode()メソッドとequals()メソッドを書き直します。
hashcode()とequals()を書き換えるStudent.javaのコードは次のとおりです。
package com.hw.set;
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
3.LinkedHashSetコレクション
- LinkedHashSetの基礎となるデータ構造は、ハッシュテーブルとリンクリストで構成されます
- ハッシュテーブルで表される要素の一意性
- リンクリストにより、要素が順番に並んでいることが保証されます(保存順序と取得順序は同じです)。
package com.hw.set;
import java.util.LinkedHashSet;
/**
* LinkedHashSet存储字符串并遍历
*
* @author HW
*
*/
public class LinkedHashSetDemo {
public static void main(String[] args) {
// 创建集合对象
LinkedHashSet<String> lhs = new LinkedHashSet<String>();
// 添加元素
lhs.add("Python");
lhs.add("Fiddler");
lhs.add("Selenium");
// 增强for循环遍历集合
for (String str : lhs) {
System.out.println(str);
}
}
}
操作の結果は次のとおりです。
Python
Fiddler
Selenium
4.TreeSetコレクション
TreeSetは、特定のルールに従って要素を並べ替えることができます。
並べ替え方法は2つあります。どちらの方法を使用するかは、使用する工法によって異なります。工法が空の場合は、自然な順序で並べ替えられます。
- 自然順序付け:要素が属するクラスに自然順序付けインターフェイスComparable <T>を実装させます。まず、Comparable <T>インターフェイスとcompareTo()メソッドを理解しましょう。
- public interface Comparable <T>:このインターフェイスは、それを実装する各クラスのオブジェクトの全体的な順序を強制します。この順序は、クラスの自然順序と呼ばれます。クラスのcompareTo()メソッドは、クラスの自然比較メソッドと呼ばれます。
- int compareTo(T o):オブジェクトが指定されたオブジェクトよりも小さい、等しい、または大きい場合、それぞれ負の整数、ゼロ、または正の整数を返します。
- コンパレータの並べ替え:コレクションの構築メソッドが、コンパレータインターフェイスのサブクラスオブジェクトComparatorを受け取るようにします。
TreeSetの最下層は、要素の並べ替えと一意性を確保するためのバイナリツリー構造です。
4.1 TreeSetは、整数型の要素とトラバースを格納します
// 创建集合对象
TreeSet<Integer> ts = new TreeSet<Integer>();
// 添加元素
ts.add(20);
ts.add(23);
ts.add(15);
ts.add(6);
ts.add(18);
ts.add(23);
// 增强for遍历集合
for (Integer i : ts) {
System.out.println(i);
}
演算結果:
6
15
18
20
23
4.2 TreeSetは、カスタムオブジェクトとトラバースを格納します
- 学生(名前、年齢)
- 年齢で若いものから古いものへと並べ替える
4.2.1自然順を使用する
自然ソートを使用して学生オブジェクトをソートするには、StudentクラスはComparable <T>インターフェイスを実装し、compareTo()メソッドをオーバーライドする必要があります。StudentクラスがComparable <T>インターフェースを実装していない場合、操作結果はエラーを報告します:スレッド "main"の例外java.lang.ClassCastException:com.hxs.day06.Studentをjava.lang.Comparableにキャストできません、以下に示すように:
次に、このインターフェイスをStudentクラスに実装し、compareTo()メソッドをオーバーライドします。
package com.hw.treeset;
/**
* 如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
*
* @author HW
*
*/
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int compareTo(Student s) {
// 主要条件,按照年龄排序
int num = this.age - s.age;
// 次要条件,年龄相同的时候,比较姓名是否相同
// 如果年龄和姓名都相同,才是同一个元素
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
}
テストコードは次のとおりです。
package com.hw.treeset;
import java.util.TreeSet;
import com.hw.set.Student;
/**
* TreeSet存储自定义对象并遍历
* 自然排序,按照年龄从小到大排序
*
* @author HW
*
*/
public class TreeSetDemo2 {
public static void main(String[] args) {
// 创建集合对象
TreeSet<Student> ts = new TreeSet<Student>();
// 创建学生对象
Student s1 = new Student("linqingxia", 27);
Student s2 = new Student("zhangguorong", 29);
Student s3 = new Student("wanglihong", 23);
Student s4 = new Student("linqingxia", 27);
Student s5 = new Student("liushishi", 22);
Student s6 = new Student("wuqilong", 40);
Student s7 = new Student("fengqingy", 22);
// 把学生对象添加到集合中
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
// 增强for遍历集合
for (Student stu : ts) {
System.out.println(stu.getName() + "---" + stu.getAge());
}
}
}
操作の結果は次のとおりです。
fengqingy---22
liushishi---22
wanglihong---23
linqingxia---27
zhangguorong---29
wuqilong---40
4.2.2コンパレータのソート
コレクションのコンストラクターが、コンパレーターインターフェイスのサブクラスオブジェクトComparatorを受け取るようにします。
package com.hw.treeset;
import java.util.Comparator;
import java.util.TreeSet;
import com.hw.set.Student;
/**
* TreeSet存储自定义对象并遍历
* 比较器排序
*
* @author HW
*
*/
public class TreeSetDemo3 {
public static void main(String[] args) {
// 创建集合对象
// 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象
// 而匿名内部类就可以实现这个东西
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
: num;
return num;
}
});
// 创建学生对象
Student s1 = new Student("linqingxia", 27);
Student s2 = new Student("zhangguorong", 29);
Student s3 = new Student("wanglihong", 23);
Student s4 = new Student("linqingxia", 27);
Student s5 = new Student("liushishi", 22);
Student s6 = new Student("wuqilong", 40);
Student s7 = new Student("fengqingy", 22);
// 把学生对象添加到集合中
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
// 增强for遍历集合
for (Student stu : ts) {
System.out.println(stu.getName() + "---" + stu.getAge());
}
}
}
実行結果は次のとおりです:
liushishi---22
wanglihong---23
linqingxia---27
zhangguorong---29
wuqilong---40