起始目录导引:
Collection接口
|------List接口:存储有序的,可以重复的元素
|----------ArrayList(主要的实现类)、LinkedList、Vector
|------Set接口:
|----------HashSet、LinkedHashSet、TreeSet
Map接口:存储"键--值"对的数据:
|------HashMap、LinkedHashMap、TreeMap、HashTable(子类:properties)
导包用:Ctrl+Shift+O;
接口创建对象的写法:接口名 变量名=new 接口内的类名();
总、Collection接口:
壹
Collection接口的List子接口:有序的
一、Collection接口的实现:
- Collection是一个接口,我们通过Collection接口的子接口的一个具体实现类ArrayList来说明了Collection中含有的一些方法;创建接口对象的写法:接口名 变量名=new 子接口内的实现方法的类名();
关于Collection接口的代码介绍:(代码中存在多个单元测试@Test如果想运行其中的某个,需要选中@Test下方的方法名(只要方法名,小括号除外)-->右键-->Run As-->JUnit Test)
Collection接口中的方法的代码解析:
package com.atguigu.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import org.junit.Test;
/*
* 1、存储对象可以考虑:①、数组;②、集合
* 2、数组存储对象的特点:Student[] stu=new Student[20];stu[0]=new Student();........
* -->弊端:①、一旦创建,长度不可变。如:银行存顾客,如果用数组,受限制。②、真实的数组存放的对象的个数是不可知的。
* 3、集合
* Collection接口
* |------List接口:存储有序的,可以重复的元素
* |----------ArrayList、LinkedList、Vector
* |------Set接口:
* |----------HashSet、LinkedHashSet、TreeSet
* Map接口:存储"键--值"对的数据:
* |------HashMap、LinkedHashMap、TreeMap、HashTable(子类:properties)
*
* */
public class TestCollection {
@Test
public void testCollection3() {
Collection coll=new ArrayList();//Collection是一个接口,接口创建时new的是一个接口内的类。
//1、size()方法:返回集合中元素的个数
System.out.println(coll.size());
//2、add(Object obj):向集合中添加元素
coll.add(123);
coll.add("AA");
coll.add(new Date());
coll.add("BB");
// coll.add(new Person("MM",23));
Collection coll1=new ArrayList();
coll1.add(123);
coll1.add(new String("AA"));
//10、removeAll(Collection coll):从当前几何中删除包含在coll中的元素。
coll.removeAll(coll1);
System.out.println(coll);
//11、equals(Object obj):两个集合是否完全相同
//12、hashCode():计算集合中的Hash值,
System.out.println("########");
//13、toArray():将集合转化成数组
Object[] obj=coll.toArray();
for(int i=0;i<obj.length;i++) { //数组的遍历
System.out.println(obj[i]);
}
//14、iterator():返回一个Iterator接口实现类的对象,进而实现集合的遍历;遍历集合中的元素
Iterator iterator=coll.iterator();
//集合的遍历方式一:用System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.hasNext());
// System.out.println(iterator.hashCode());
// System.out.println(iterator.next());
System.out.println("分隔线------------------");
// //集合的遍历方式二:使用for语句
// for(int i=0;i<coll.size();i++) {
// System.out.println(iterator.next());
// }
//方式三:常用
while(iterator.hasNext()) {//下一个是否有hash值
System.out.println(iterator.next());
}
}
@Test
public void testCollection2() {
Collection coll=new ArrayList();//Collection是一个接口,接口创建时new的是一个接口内的类。
//1、size()方法:返回集合中元素的个数
System.out.println(coll.size());
//2、add(Object obj):向集合中添加元素
coll.add(123);
coll.add("AA");
coll.add(new Date());
coll.add("BB");
// Person p=new Person("MM",23);
// coll.add(p); 两句和为一句:coll.add(new Person(“MM”,23));
// System.out.println(p); //true
// boolean b2=coll.contains(new Person("MM",23));
// System.out.println(b2); //false
//6、contains(Object obj):判断集合中是否包含指定的obj元素。如果包含,返回true;反之,返回false。
//判断依据:根据元素所在类的equals()方法。
//明确:如果存入集合中的元素是自定义类的对象。要求:自定义类要重写equals()方法!
boolean b1=coll.contains(23);
System.out.println(b1);
//7、containsAll(Collection coll):判断当前集合中是否包含coll中所有的元素
Collection coll1=new ArrayList();
coll1.add(123);
coll1.add(new String("AA"));
boolean b3=coll.containsAll(coll1); //true
System.out.println("#"+b3);
coll1.add(456);
//8、returnAll(Collection coll1):形参为一个集合;求当前集合与coll的共有元素,返回给当前集合
coll.retainAll(coll1);
System.out.println(coll);
//9、remove(Object obj):删除集合中的obj元素,删除成功返回true;反之false。
boolean b4=coll.remove("BB");
System.out.println(b4);
//10、
}
@Test//单元测试
public void testCollection1() {
Collection coll=new ArrayList();//Collection是一个接口,接口创建时new的是一个接口内的类。
//1、size()方法:返回集合中元素的个数
System.out.println(coll.size());
//2、add(Object obj):向集合中添加元素
coll.add(123);
coll.add("AA");
coll.add(new Date());
coll.add("BB");
System.out.println(coll.size()); //4
//3、addAll(Collection coll):将形参coll1中包含的所有元素添加到当前集合中
Collection coll1=Arrays.asList(1,2,3); //数组转化为了集合。
coll.addAll(coll1);
System.out.println(coll.size()); //7
//查看集合元素:直接打印引用名即可查看集合元素
System.out.println(coll);
//4、isEmpty():判断集合是否为空
System.out.println(coll.isEmpty()); //false
//5、clear():清空集合元素
coll.clear();
System.out.println(coll.isEmpty()); //true
}
}
二、集合遍历的方法的代码解析(代码中介绍了很多遍历方法):
package com.atguigu.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import org.junit.Test;
public class TestIterator {
//面试题:
@Test
public void testFor3() {
String[] str=new String[] {"AA","BB","C","D","E"};
for(String s:str) {
s="MM";//此处的s是新定义的局部变量,其值的修改不会对str本身造成修改;并不改变真正集合中元素的值
System.out.println(s);
}
for(int i=0;i<str.length;i++) {
System.out.println(str[i]);
}
}
//结果:
//MM
//MM
// MM
// MM
// MM
// AA
// BB
// C
// D
// E
@Test
public void testFor2() {
String[] str=new String[] {"AA","BB","C","D","E"};
for(int i=0;i<str.length;i++) {
str[i]=i+" "; //将集合中的真正元素的值给改了
}
for(int i=0;i<str.length;i++) {
System.out.println(str[i]);
}
}
//使用增强for循环实现数组的遍历
@Test
public void testFor1() {
String str[]=new String[] {"123","Bb","ABC","Hello"};
for(String s:str) {
System.out.println(s);
}
}
//使用增强for循环实现集合的遍历
@Test
public void testFor() {
Collection coll=new ArrayList();
coll.add(123);
coll.add(new String("AA"));
coll.add(new Date());
coll.add("ABCDEF");
coll.add(new Person("MM",23));
for(Object i:coll) { //要遍历元素的类型 变量:要遍历的集合;局部变量相当于每次取出coll集合中的一个赋给i;
System.out.println(i);
}
}
//使用迭代器遍历集合元素
@Test
public void test1() {
Collection coll=new ArrayList();
coll.add(123);
coll.add(new String("AA"));
coll.add(new Date());
coll.add(new Person("MM",23));
Iterator i=coll.iterator();
while(i.hasNext()) {//hasNext():判断集合中的下一个元素是否有值,从而可以知道是否存在下一个元素。
System.out.println(i.next());//执行.next();:会把当前的集合中元素的值返回,并且指向下一个元素
}
}
// @Test
/* 有错误的写法 */
// public void test2() {
// Collection coll=new ArrayList();
// coll.add(123);
// coll.add(new String("AA"));
//
// coll.add(new Date());
// coll.add(new Person("MM",23));
//
// Iterator i=coll.iterator();
// while(i.next()!=null) {//hasNext():判断集合中的下一个元素是否有值,从而可以知道是否存在下一个元素。
// System.out.println(i.next());//执行.next();:会把当前的集合中元素的值返回,并且指向下一个元素
// } java.util.NoSuchElementException错误
// }
}
三、ArrayList及List的常用方法:
常用方法代码实现解析:
package com.atguigu.collection;
import java.awt.List;
import java.util.ArrayList;
import org.junit.Test;
/*
* List常用的方法:
* 增(add(Object obj))、删(remove)、改(set(int index,Object obj));
* 查(get(int index))、插(add(int index,Object ele))、长(size())。
* */
public class TestList {
//ArrayList:List的主要实现类
@Test
public void testList2() {
ArrayList list=new ArrayList();
list.add(123);
list.add("AA");
list.add(456);
list.add("BB");
list.add("AA");
System.out.println(list.indexOf(456));
System.out.println(list.indexOf(12));
System.out.println(list.lastIndexOf("AA"));
System.out.println(list.indexOf(123)==list.lastIndexOf(123));
System.out.println(list.subList(1, 3));//左闭右开
}
@Test
public void testList1() {
ArrayList list=new ArrayList();
list.add(123);
list.add("AA");
list.add(456);
list.add("BB");
System.out.println(list);
list.add(0,666);//1、在指定位置处添加元素
System.out.println(list);
Object obj=list.get(3);//2、获取指定位置处的元素
System.out.println(obj);
//3、remove();--删除与指定位置的元素
//4、set( , );--设置指定位置的元素为某某
}
}
四、LinkedList类及Vector类的使用
1、ArrayList使用数组连接;而LinkedList则是使用链表联系在一起。(对于频繁的插入与删除操作建议选择用LinkedList)。
2、Vector:古老的类,线程安全的;插入、删除等操作比较慢。
五、笔记总结:
贰
Collection接口的Set子接口:无序的
Set接口:存储的元素是无序的,不可重复的!
1、无序性:无序性!=随机性。真正的无序性,指的是元素在底层存储的位置是无序的。
2、不可重复性:当向Set中添加进相同的元素时,后面的这个不能添加进去。
3、如果要添加进Set中的元素所在的类,一定要重写equals()和hashCode()方法。
进而保证Set中元素的不可重复性。
4、如果要保存在Set中一定要重写Object类的equals()和hashCode()方法;如果要存储在List中则不需要重写hashCode方法。
5、正因为Set中的元素是无序的,才用到了重写hashCode方法。
6、Set中的元素是如何存储的呢?使用了哈希算法。
当向Set中添加对象时,首先调用此对象所在的hashCode()方法,
计算此对象的哈希值,此哈希值决定了此对象在Set中的存储位置。
若此位置之前没有对象存储,则这个对象直接存储到此位置。
若此位置已有对象存储,再通过equals()方法比较这两个对象是否相同。如果相同,后一个对象就不能再添加进来。
6-万一返回false呢,都存储。(不建议这样)。
>如果保存在Set中要求hashCode()方法一定要与equals()方法一致。
一、HashSet实例演示:
①、Person类:
package com.atguigu.collection;
public class Person {
int id=1002;
private String name;
private int age;
//有参的构造方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() { //无参的构造方法
super();
}
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 void walk() {
System.out.println("人走路");
}
public void eat() {
System.out.println("人吃饭");
}
@Override //用于Set接口比较
public int hashCode() {//1、return age.hashCode()+name.hashCode();没有下述的健壮性好。
//2、建议直接用系统自动生成的。
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
// 3、return init++;//不建议这样用
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
②、TestSet类:
package com.atguigu.collection;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
/*
* Collection接口
* |------List接口:存储有序的,可以重复的元素。List中常用的方法除了Colletion中的抽象方法在List子接口的类中实现的之外;还有自己特有的。
* |----------ArrayList(主要的实现类)、LinkedList(对于频繁的插入、删除操作)、Vector
* |------Set接口:存储无序的不可重复的元素。Set中常用的方法都是Collection下定义的。
* |----------HashSet(主要实现类)、
* LinkedHashSet、
* TreeSet
*
* */
public class TestSet {
/*Set接口:存储的元素是无序的,不可重复的!
* 1、无序性:无序性!=随机性。真正的无序性,指的是元素在底层存储的位置是无序的。
* 2、不可重复性:当向Set中添加进相同的元素时,后面的这个不能添加进去。
* 3、如果要添加进Set中的元素所在的类,一定要重写equals()和hashCode()方法。
* 进而保证Set中元素的不可重复性。
* 4、如果要保存在Set中一定要重写Object类的equals()和hashCode()方法;如果要存储在List中则不需要重写hashCode方法。
* 5、正因为Set中的元素是无序的,才用到了重写hashCode方法。
*
*Set中的元素是如何存储的呢?使用了哈希算法。
* 当向Set中添加对象时,首先调用此对象所在的hashCode()方法,
*计算此对象的哈希值,此哈希值决定了此对象在Set中的存储位置。
*若此位置之前没有对象存储,则这个对象直接存储到此位置。
*若此位置已有对象存储,再通过equals()方法比较这两个对象是否相同。如果相同,后一个对象就不能再添加进来。
* 万一返回false呢,都存储。(不建议这样)。
* >要求hashCode()方法要与equals()方法一致。
* */
@Test
public void testHashSet() {
Set set=new HashSet();
set.add(123);
set.add("AA");
set.add(new String("AA"));
set.add(new String("AA")); //重新new的也不可以重复,两个重新new的和直接 .add("AA");三个只会显示一个"AA";
set.add(456);
set.add("BCD");
set.add(null);
Person p1=new Person("GG",23);
Person p2=new Person("GG",23); //Person p2=new Person("MM",21);
/*
* 如果上方为Person p1=new Person("GG",23);
* 仍然结果与之前相同,因为这是两个对象,在Set比较二者时,
* 调用的是equals方法,而在Person中没有重写equals方法,
* 所以调用的是Object类中的equals方法,
* Object类中的equals方法比较的是地址值是否相同
*/
System.out.println(p1.equals(p2));
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
set.add(p1);
set.add(p2);
System.out.println(set.size());
System.out.println(set);
}
}
二、LinkedHashSet的特点及实现:
图解:LinkedGHashSet在存储的时候是用链表的方式;不像数组那样通过下脚标可以找到相应的元素,而LinkedHashSet在用链表存储时没有下脚标,是无序的,但是却维护了添加进去的顺序。
1、LinkedHashSet是HashSet的子类。
2、LinkedHashSet根据元素的hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
3、LinkedHashSet插入性能略低于HashSet,但在迭代访问Set里的全部元素时有很好的性能。
4、LinkedHashSet不允许集合元素重复。
5、LinkedHashSet:使用链表维护了一个添加进集合中的顺序;导致当我们遍历LinkedHashSet集合元素时,是按照添加进去的顺序遍历的。
代码(LinkedHashSet):
public class TestSet {
/*
* LinkedHashSet:使用链表维护了一个添加进集合中的顺序。
* 导致当我们遍历LinkedHashSet集合元素时,是按照添加进去的顺序遍历的。
*
* */
@Test
public void testLinkedHashSet() {
Set set=new LinkedHashSet();
set.add(123);
set.add("I ");
set.add(456);
set.add("Love");
set.add(new String("abc"));
set.add(new String("abc"));
set.add(new Person("MM",21));
set.add(null);
Iterator iterator=set.iterator();//迭代器
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
三、TreeSet的自然排序:
TreeSet:
1、向TreeSet中添加的元素必须是同一个类型的。
2、可以按照添加进集合中的元素的指定顺序遍历。像String、包装类等默认按照从小到大的顺序遍历。
3、当向TreeSet中添加自定义的对象时,有两种排序方法:①、自然排序;②、定制排序。当自然排序与定制排序混合在一起的话,以定制排序优先。
4、自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)方法
在此方法中,指明按照自定义类的哪个属性进行排序。
5、向TreeSet中添加元素时,首先按照compareTo()方法进行比较,一旦返回0,虽然仅仅是两个对象的
此属性值相同,但是程序会认为这两个对象是相同的,进而后一个对象就不能添加进来。
>compareTo()与hashCode()以及equals()三者保持一致。
1、Person类:
package com.atguigu.collection;
public class Person implements Comparable{
int id=1002;
private String name;
private Integer age;
//有参的构造方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() { //无参的构造方法
super();
}
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 void walk() {
System.out.println("人走路");
}
public void eat() {
System.out.println("人吃饭");
}
@Override //用于Set接口比较
public int hashCode() {//1、return age.hashCode()+name.hashCode();没有下述的健壮性好。
//2、建议直接用系统自动生成的。
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
// 3、return init++;//不建议这样用
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
//向TreeSet中添加Person类的对象时,依据此方法,确定按哪个属性排列。
@Override
public int compareTo(Object o) {
if(o instanceof Person) {
Person p=(Person)o;
// return this.name.compareTo(p.name);//此处是按照name属性进行排序的。
// return -this.age.compareTo(p.age);//加上负号表示由大到小
// return this.age.compareTo(p.age);//按照age进行排序(age是Integer类型的,Integer也实现了compareTo方法)。
// 自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)方法
// 在此方法中,指明按照自定义类的哪个属性进行排序。
// 为了使相同的也能写进TreeSet像数据库一样,有一级排序,一级排序相同再二级排序
/*实现的是先按照age从小到大排,age相等按name排*/
int i=this.age.compareTo(p.age);
if(i==0) {//如果有age相等的则按名字排序
return this.name.compareTo(p.name);
}else {//如果age不等则按age排序
return i;
}
}
return 0;
}
}
2、TestSet类中的testTreeSet()方法部分:
public class TestSet {
/*
* TreeSet:
* 1、向TreeSet中添加的元素必须时同一个类型的。
* 2、可以按照添加进集合中的元素的指定顺序遍历。像String、包装类等默认按照从小到大的顺序遍历。
* 3、当向TreeSet中添加自定义的对象时,有两种排序方法:①、自然排序;②、定制排序。
* 4、自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)方法
* 在此方法中,指明按照自定义类的哪个属性进行排序。
*
* 5、向TreeSet中添加元素时,首先按照compareTo()方法进行比较,一旦返回0,虽然仅仅是两个对象的
* 此属性值相同,但是程序会认为这两个对象是相同的,进而后一个对象就不能添加进来。
*
* >compareTo()与hashCode()以及equals()三者保持一致。
* */
@Test
public void testTreeSet() {
Set set=new TreeSet();
// set.add(new String("AAA"));
// set.add(new String("BBB"));
// set.add("CD");
set.add(123); //TreeSet中添加的元素必须是同一个类型的,此处添加了两个int类型的。
set.add(456);
// set.add("EFG");
/*当Person类没有实现Comparable接口时,当向TreeSet中添加Person对象时,报ClassCastException错误*/
set.add(new Person("YY",24));
set.add(new Person("XX",22));
set.add(new Person("DD",21));/*在Person中对应实现的是先按照age从小到大排,age相等按name排*/
set.add(new Person("TT",23));
set.add(new Person("KK",23));
// set.add("AA");出错(编译时不会有错,在真正运行时才会出错)因为和上面的类型不匹配
for(Object str:set) {
System.out.println(str);
}
}
}
四、TreeSet的定制排序:
1、Customer类的代码:
package com.atguigu.collection;
public class Customer {
private String name;
private int id;
//Getters & Setters方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//构造器
public Customer(String name, int id) {
super();
this.name = name;
this.id = id;
}
//toString方法
@Override
public String toString() {
return "Customer [name=" + name + ", id=" + id + "]";
}
//hashCode & equals()方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
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;
Customer other = (Customer) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
2、TestSet类中testTreeSet2()方法的代码:
public class TestSet {
/*
* TreeSet的定制排序:
* 如下的1、2、3部。
* compare()与hashCode()以及equals()三者保持一致。
*
* */
@Test
public void testTreeSet2(){
//1、创建一个实现了Comparator接口的类对象
Comparator com=new Comparator() {//Comparator中有equals和compare两个,但此处只是重写了compare,因为Comparator继承Object,Object中自动重写equals。
//向TreeSet中添加Customer类的对象,在此compare()方法中,指明是按照Customer
//的哪个属性排序的。上次的Person中是在compareTo()方法中写排序。
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Customer && o2 instanceof Customer) {
Customer c1=(Customer)o1;
Customer c2=(Customer)o2;
int i= c1.getId().compareTo(c2.getId());
// 先按id排,id一样再按name排
if(i==0) {
return c1.getName().compareTo(c2.getName());
}else {
return i;
}
}
return 0;
}
};//不能缺少";"号
//2、将此对象作为形参传递给TreeSet的构造器
TreeSet set=new TreeSet(com);
//3、向TreeSet中添加Comparator接口中的compare方法中涉及的类的对象
set.add(new Customer("AA",1003));
set.add(new Customer("BB",1002));
set.add(new Customer("GG",1004));
set.add(new Customer("CC",1001));
set.add(new Customer("DD",1007));
// 如果有两个id号一样的就只显示其中一个,另一个进不去
for(Object str:set) {//遍历
System.out.println(str);
}
}
}
五、TreeSet的使用练习:
1、当自然排序与定制排序混合在一起的话,以定制排序优先。
2、一般情况下,一个实体类中的多个对象如果按自然排序,需要实现重写Comparable接口;如果按定制排序,不需要实体类什么Comparable接口在创建TreeSet时需要传入Comparator对象格式如下:
Comparator com=new Comparator() {//先造一个Comparator接口实现类的一个对象
@Override //实现
public int compare(Object arg0, Object arg1) {
// TODO Auto-generated method stub
return 0;
}
};
用int型来定义的变量就不能调用compareTo()方法。
题目要求:
代码解析:
1、MyDate类代码:
package com.atguigu.exec;
public class MyDate {
private int day;
private int month;
private int year;
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public MyDate(int day, int month, int year) {
super();
this.day = day;
this.month = month;
this.year = year;
}
@Override
public String toString() {
return "MyDate [day=" + day + ", month=" + month + ", year=" + year + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + day;
result = prime * result + month;
result = prime * result + year;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyDate other = (MyDate) obj;
if (day != other.day)
return false;
if (month != other.month)
return false;
if (year != other.year)
return false;
return true;
}
}
2、Employee类的代码:
package com.atguigu.exec;
public class Employee implements Comparable{
private String name;
private Integer age;
private MyDate birthday;
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 MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
public Employee(String name, int age, MyDate birthday) {
super();
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee [name=" + name + ", age=" + age + ", birthday=" + birthday + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((birthday == null) ? 0 : birthday.hashCode());
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;
Employee other = (Employee) obj;
if (age != other.age)
return false;
if (birthday == null) {
if (other.birthday != null)
return false;
} else if (!birthday.equals(other.birthday))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public int compareTo(Object o) {//只是按名字排序,并没写名字相同后按什么排序。
if(o instanceof Employee) {
Employee e=(Employee)o;
return this.name.compareTo(e.name);
// int i=this.name.compareTo(e.name);
// if(i==0) { /* 按照年龄从小到大 */
// return this.age.compareTo(e.age);
// }else {
// return i;
// }
}
// return 0;
return 0;
}
}
3、Employee1类的代码:
package com.atguigu.exec;
public class Employee1{
private String name;
private Integer age;
private MyDate birthday;
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 MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
public Employee1(String name, int age, MyDate birthday) {
super();
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee [name=" + name + ", age=" + age + ", birthday=" + birthday + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((birthday == null) ? 0 : birthday.hashCode());
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;
Employee1 other = (Employee1) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (birthday == null) {
if (other.birthday != null)
return false;
} else if (!birthday.equals(other.birthday))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
4、TestEmployee类的代码:
package com.atguigu.exec;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
import org.junit.Test;
public class TestEmployee {
//2、定制排序:创建TreeSet时传入Comparator对象
@Test//按照生日的先后排序
public void test2() {
Comparator com=new Comparator() {//先造一个Comparator接口实现类的一个对象
@Override //实现
public int compare(Object o1, Object o2) {
if(o1 instanceof Employee1 && o2 instanceof Employee) {
Employee1 e1=(Employee1)o1;//向上转型
Employee1 e2=(Employee1)o2;
MyDate birth1=e1.getBirthday();
MyDate birth2=e2.getBirthday();
if(birth1.getYear() != birth2.getYear()) {
return birth1.getYear() - birth2.getYear();
}else{
if(birth1.getMonth() != birth2.getMonth()) {
return birth1.getMonth() - birth2.getMonth();
}else {
return birth1.getDay() - birth2.getDay();
}
}
}
return 0;
}
};
TreeSet set=new TreeSet(com);
//之后就可以添加Employee1的实体类了
Employee1 e1=new Employee1("刘德华", 55, new MyDate(4, 12, 1976));
Employee1 e2=new Employee1("郭富城", 43, new MyDate(7, 3, 1954));
Employee1 e3=new Employee1("张学友", 33, new MyDate(9, 3, 1954));
Employee1 e4=new Employee1("黎明", 54, new MyDate(12, 2, 1954));
Employee1 e5=new Employee1("李敏镐", 65, new MyDate(4, 21, 1945));
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
set.add(e5);
//遍历
Iterator iterator=set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
// 1、自然排序:使Employee实现Comparable接口,并按name排序
@Test
public void test1() {
Employee e1=new Employee("刘德华", 55, new MyDate(4, 12, 1976));
Employee e2=new Employee("郭富城", 43, new MyDate(7, 3, 1965));
Employee e3=new Employee("张学友", 33, new MyDate(9, 12, 1954));
Employee e4=new Employee("黎明", 54, new MyDate(12, 2, 1967));
Employee e5=new Employee("李敏镐", 65, new MyDate(4, 21, 1945));
//下面的与上一条名字一样,后边信息都不同,但是加不进TreeSet中,
//因为在Employee中重写的compareTo()方法里只用名字比较来完成排序。
//如果要加进TreeSet中,在Employee的compareTo()方法中设置,先用名字排序,名字相同再用年龄或生日排序
Employee e6=new Employee("李敏镐", 49, new MyDate(3, 2, 1993));
TreeSet set=new TreeSet();
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
set.add(e5);
set.add(e6);
//遍历
Iterator iterator=set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
//结果:按照姓名排,即姓的首字母a-b-c-d....
//Employee [name=刘德华, age=55, birthday=MyDate [day=4, month=12, year=1976]]
//Employee [name=张学友, age=33, birthday=MyDate [day=9, month=12, year=1954]]
//Employee [name=李敏镐, age=65, birthday=MyDate [day=4, month=21, year=1945]]
//Employee [name=郭富城, age=43, birthday=MyDate [day=7, month=3, year=1965]]
//Employee [name=黎明, age=54, birthday=MyDate [day=12, month=2, year=1967]]
}