HashSet
HashSet的特点:数据结构是哈希表、元素是无序(存入和取出的顺序不一定一致),字符串元素不可以重复;
探究HashSet判断元素重复问题
原理:利用HashSet调用add方法的同时底层会自动调用HashCode()和equals()方法,重写两个方法,HashCode()比较的是内存地址,equals()比较的是元素内容
class Person{
private String name;
private int 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 Person() {}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
/**重写HashCode()
* 返回值代表容器中的具体位置的坐标
*/
@Override
public int hashCode() {
return this.getName().hashCode()+this.age;
}
@Override
public String toString() {//最好是写上一个toString方法,以便于更清晰的查看数据
// TODO Auto-generated method stub
return this.name+":"+this.age;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
if(obj instanceof Person) {
Person p=(Person) obj;
return this.getName().equals(p.getName())&&this.getAge()==p.getAge();
}
return super.equals(obj);
}
}
public class HashSetDemo {
public static void main(String[] args) {
//版本改变有它的默认排序
HashSet hs=new HashSet();
hs.add(new Person("aa", 18));
hs.add(new Person("bb",13));
hs.add(new Person("cc",12));
hs.add(new Person("dd",23));
hs.add(new Person("aa",18));
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
最后结果为:第二个一样的aa已经没有加进来了
TreeSet
TreeSet数据结构(二叉树)
可以对set集合进行排序,底层数据结构是二叉树;
保证元素唯一性的依据是,compareTo方法return 0
Comparable接口的用途?
使添加的元素自身具备排序规则
比较器comparator接口作用
使得容器具有比较性
操作:利用TreeSet的Comparator和compareTo实现按规则的自然排序
题目:利用Comparable实现自然排序
//实现Comparable接口
class Person implements Comparable<Person>{
private String name;
private int 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 Person() {}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {//最好是写上一个toString方法,以便于更清晰的查看数据
// TODO Auto-generated method stub
return this.name+":"+this.age;
}
/**返回值
* 正数:后面的o比前面(this)大
* 负数:前面的o比后面的(this)大
* 0代表相等
*/
//排序
@Override
public int compareTo(Person o) {
int num=this.getAge()-o.getAge();
if(num==0) {//如果年龄相同就按姓氏排序
return this.getName().compareTo(o.getName());
}
return this.getAge()-o.getAge();
}
}
public class TreeSetDemo {
public static void main(String[] args) {
//版本改变有它的默认排序
TreeSet hs=new TreeSet();
//==0就是它的判断重复
hs.add(new Person("aa",18));
hs.add(new Person("bb",13));
hs.add(new Person("cc",12));
hs.add(new Person("dd",23));
hs.add(new Person("aa",18));
hs.add(new Person("ee",23));
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
效果为
题目:利用Comparator对用户表中的排序规则进行更改(先按姓氏、再按年龄)
/**
* 定义一个比较person的比较器
* 规则:先按姓氏、再按年龄
* 先主要条件再次要条件,如果不按照这个规则来,那么数据会丢失
*实体类还是前面那个Person
*/
class PersonComp implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
int num=o1.getName().compareTo(o2.getName());
if(num==0) {
return o1.getAge()-o2.getAge();
}
return num;
}
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet hs=new TreeSet(new PersonComp());
hs.add(new Person("aa", 18));
hs.add(new Person("bb",13));
hs.add(new Person("cc",12));
hs.add(new Person("dd",23));
hs.add(new Person("ee",23));
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
结果为先按了姓氏排序再按年龄排序
泛型
概念:JDK1.5之后以类型作为参数的类就叫泛型,泛型的默认值是Object
作用:提高程序健壮性,简化代码
值类型->引用类型 装箱(值类型:int、float等等)
引用类型->值类型 拆箱(引用类型:我们定义的类型、Integer等)
jdk1.5之后引入了自动装箱及自动拆箱功能
<? super A>: 表示泛型的类型只能是A类或者A类的父类。 下限,最低到A类。
<? extends A>:表示泛型的类型只能是A类或者A类的子类。 上限,最高到A类。
下面我们来写一个例题,利用下限定和TreeSet实现子类的排序
/**
* 写一个Student类继承Person
*Person类还是上面那个Person,一样的实现了Comparable接口
*/
class Student extends Person{
private String name;
private int 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 Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {}
@Override
public String toString() {//最好是写上一个toString方法,以便于更清晰的查看数据
// TODO Auto-generated method stub
return this.name+":"+this.age;
}
}
/**
* 定义一个比较器
* 这个比较器Person下面所有的子类都可以用
*/
class ComPerson implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
// TODO Auto-generated method stub
return o1.getAge()-o2.getAge();
}
}
public static void main(String[] args) {
// ArrayList <Student>list = new ArrayList<>();
TreeSet list=new TreeSet<>(new ComPerson());
list.add(new Student("aa", 12));
list.add(new Student("bb", 22));
list.add(new Student("cc", 11));
button(list);//调用了下面的下限定TreeSet排序
}
/**
* 上限定案例
* @param al
*/
public static void up(ArrayList<? extends Person> al) {
Iterator<?> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
/**
* 下限定案例
* 利用TreeSet和上限定进行自然排序
* @param al
*/
public static void button(TreeSet<? extends Person> al) {
Iterator<?> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
结果为Student的数据全部输出,并且按照了年龄排序