set
元素不可重复,无序
通过分析HashSet的add()方法源码得知,添加不重复元素的关键在于两个方法:(1)hashCode()方法;(2)equals()方法
如果添加的是引用类型,那么需要重写这两个方法,原因在于HashMap的put方法中是这两个方法进行判断的。
package com.mcq;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javafx.beans.binding.StringBinding;
public class SetDemo {
public static void main(String[] args) {
Set<String> set=new HashSet<String>();
set.add("小明");
set.add("小花");
set.add("小丽");
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){
String next=iterator.next();
System.out.println(next);
}
System.out.println(set.contains("小明"));
for(String str:set){
System.out.println(str);
}
}
}
重写hashCode方法和equals方法:
//Student.java
package com.mcq;
public class Student {
private String name;
private int age;
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() {
// TODO Auto-generated method stub
return -1;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(this==obj)
return true;
if(!(obj instanceof Student)){
return false;
}
else {
Student student=(Student)obj;
if(student.getAge()==this.getAge()&&student.name==this.getName()){
return true;
}
return false;
}
}
}
//SetDemo.java
package com.mcq;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javafx.beans.binding.StringBinding;
public class SetDemo {
public static void main(String[] args) {
Set<Student> set=new HashSet<Student>();
set.add(new Student("小明",19));
set.add(new Student("小强",20));
set.add(new Student("小华",21));
set.add(new Student("小强",20));
for(Student student:set){
System.out.println(student.getName()+" "+student.getAge());
}
}
}
增强for循环
语法:
for(数据类型 变量名:集合对象){
语句体;
}
所有实现了Iterable接口的实现类都可以使用foreach语句
数组也可以用
foreach的数据类型可以是基本数据类型也可以是引用。
TreeSet
1.元素不可重复
2.可以按照自然顺序排序
3.如果排序的是引用数据类型,需要实现Comparable接口
此接口需要重写compareTo()方法,此方法规定:
该对象小于、等于、大于指定对象,分别返回负数,0,正数。
实例:
方法一:实现接口Comparable
//Student.java
package com.mcq;
public class Student implements Comparable<Student>{
private String name;
private int age;
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() {
// TODO Auto-generated method stub
return -1;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(this==obj)
return true;
if(!(obj instanceof Student)){
return false;
}
else {
Student student=(Student)obj;
if(student.getAge()==this.getAge()&&student.name==this.getName()){
return true;
}
return false;
}
}
public int compareTo(Student o) {
// TODO Auto-generated method stub
if(this.getAge()<o.getAge()){
return -1;
}else if(this.getAge()==o.getAge()){
return 0;
}else {
return 1;
}
}
}
//TreeSetDemo
package com.mcq;
public class Student implements Comparable<Student>{
private String name;
private int age;
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() {
// TODO Auto-generated method stub
return -1;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(this==obj)
return true;
if(!(obj instanceof Student)){
return false;
}
else {
Student student=(Student)obj;
if(student.getAge()==this.getAge()&&student.name==this.getName()){
return true;
}
return false;
}
}
public int compareTo(Student o) {
// TODO Auto-generated method stub
if(this.getAge()<o.getAge()){
return -1;
}else if(this.getAge()==o.getAge()){
return 0;
}else {
return 1;
}
}
}
方法二:实现比较器Comparator
//MyComparator.java
package com.mcq;
import java.util.Comparator;
public class MyComparator implements Comparator<Student>{
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
if(o1.getAge()<o2.getAge()){
return -1;
}else if(o1.getAge()>o2.getAge()){
return 1;
}else {
return 0;
}
}
}
//Student.java
package com.mcq;
public class Student{
private String name;
private int age;
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() {
// TODO Auto-generated method stub
return -1;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(this==obj)
return true;
if(!(obj instanceof Student)){
return false;
}
else {
Student student=(Student)obj;
if(student.getAge()==this.getAge()&&student.name==this.getName()){
return true;
}
return false;
}
}
// public int compareTo(Student o) {
// // TODO Auto-generated method stub
// if(this.getAge()<o.getAge()){
// return -1;
// }else if(this.getAge()==o.getAge()){
// return 0;
// }else {
// return 1;
// }
// }
}
//TreeSetDemo.java
package com.mcq;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
Set<Student> set=new TreeSet<Student>(new MyComparator());
set.add(new Student("小明",18));
set.add(new Student("小华",19));
set.add(new Student("小丽",17));
for(Student student:set){
System.out.println(student.getName()+" "+student.getAge());
}
// System.out.println("hello");
}
}
方法三 :匿名内部类
package com.mcq;
import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getAge() - o2.getAge();
}
});
set.add(new Student("小明", 18));
set.add(new Student("小华", 19));
set.add(new Student("小丽", 17));
for (Student student : set) {
System.out.println(student.getName() + " " + student.getAge());
}
// System.out.println("hello");
}
}
更实用的排序方法:
package com.mcq;
import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
int t=o1.getAge() - o2.getAge();
return t==0?o1.getName().compareTo(o2.getName()):t;
}
});
set.add(new Student("小明", 18));
set.add(new Student("小华", 19));
set.add(new Student("小丽", 17));
for (Student student : set) {
System.out.println(student.getName() + " " + student.getAge());
}
// System.out.println("hello");
}
}
最后,自己之前一直不明白add的时候Comparator调用了几次,只想到了是个二叉排序树,其实TreeSet是个平衡二叉树,也就是说当二叉树不平衡时,会左旋或右旋(数据结构的基本知识)。举个栗子:
package com.mcq;
import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
System.out.println("compare...");
System.out.println(o1+" "+o2);
int t=o1.getAge() - o2.getAge();
return t==0?o1.getName().compareTo(o2.getName()):t;
}
});
set.add(new Student("1", 25));
set.add(new Student("4", 21));
set.add(new Student("2", 18));
set.add(new Student("4", 21));
set.add(new Student("3", 28));
// for (Student student : set) {
// System.out.println(student.getName() + " " + student.getAge());
// }
// System.out.println("hello");
}
}
打印结果是:
compare...
4 21 1 25
compare...
2 18 1 25
compare...
2 18 4 21
compare...
4 21 4 21
compare...
3 28 4 21
compare...
3 28 1 25
我主要是第五个Compare我出了问题,开始把(1,25)作为根节点,当(2,18)插进去的时候(1,25)的左右深度相差就大于1了,这时,就要旋转了。旋转后,(4,21)就变成了根,再插(3,28)的时候就是先和(4,21)比较了,而不是我之前想的先和(1,26)比较。。至于我是怎么发现的呢?调试呀……set子目录下有个root变量,每次看root的变化就知道了~