19.集合三
往list中存元素保证唯一性
public static void main(String[] args) {
//取出List中重复的元素
// 思路:
// 1.先创建新的临时容器,用于存储唯一性的元素
// 2.遍历之前的容器,将遍历到的元素到临时容器中进行判断,是否存在,
// 3.如果元素存在,不存在临时容器中,反之则存储
// 4.遍历结束后,临时容器中存储的就是唯一的元素
// 5.如果想要把临时的容器中唯一的元素添加到原来的容器中,只要将之前的容器清空,
// 将临时容器中的数据添加到之前的容器中
List list = new ArrayList();
list.add("abc");
list.add("abc2");
list.add("abc3");
list.add("abc3");
list.add("abc4");
List singleElement = getSingleElement(list);
System.out.println(singleElement);
}
public static List getSingleElement(List list){
// 创建一个临时容器
List temp = new ArrayList();
// 遍历原来的元素
for (Iterator it = list.iterator(); it.hasNext();) {
Object obj = it.next();//abc
// 对遍历到的每一个元素都需要去临时容器中进行判断是否包含此元素
if(!temp.contains(obj)){//如果在这个集合存在元素,则返回true,反之则false
// 将这个元素存储到临时容器中
temp.add(obj);
}
}
// 将临时容器中的所有唯一的元素存在之前的集合中
list.clear();
list.addAll(temp);
return list;
}
哈希表结构
public class Student {
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
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 hashCode(){
return name.hashCode()+age*24;
// //小一1+22 == 小一2+21
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
};
//只有当对象的hashcode相同时,才会执行equals
public boolean equals(Object obj) {
System.out.println("===");
//Object obj = s4;
if(this==obj){//同一个人
return true;
}
if(!(obj instanceof Student)){
throw new RuntimeException("类型不匹配");
}
Student s = (Student)obj;
return this.name == s.name && this.age == s.age;
}
}
}
public static void main(String[] args) {
// 创建集合 没有下标,不允许存重复元素,无序 (存进去的顺序和取出来的顺序不一致)
Set set = new HashSet();
// 添加 String重写了hashCode和equals
set.add("xixi");
set.add("hah");
set.add("coco");
set.add("hah");
set.add("hah");
// set.add(new Student("coco",18));
// set.add(new Student("小一1",22));//97+22 // 小一-->91 + 22*24
// set.add(new Student("小一2",21));//98+21 // 小一-->92 + 21*24
// set.add(new Student("小一3",23));
/*
往HashSet中存数据,先需要根据哈希算法算出哈希值(hashcode),如果哈希值不同,直接存储,不需要比较内容
如果哈希值相同(冲突),再去比较equals内容,如果内容相同,则不存储数据,因为集合中已经存在了
如果内容不同,会通过内部的拉链法再次开辟空间存储数据
*
* */
// 获取元素
for (Iterator it = set.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
TreeSet
比较排序
public static void main(String[] args) {
Set set = new TreeSet();
// set.add(3);
// set.add(1);
// set.add(8);
// set.add(1);
// set.add(7);
set.add(new Student("小一6",21));
set.add(new Student("小一8",21));
set.add(new Student("小一5",25));
set.add(new Student("小一4",18));
set.add(new Student("小一7",20));
// Comparable k = (Comparable) new Student("xiaohong",18);
// 1.继承 2.实现
// 如果想要让学生具备比较排序的功能,需要让学生类实现Comparable接口
for (Iterator it = set.iterator(); it.hasNext();) {
System.out.println( it.next());
}
}
public class Student implements Comparable{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
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 hashCode(){
return name.hashCode()+age*24;
// //小一1+22 == 小一2+21
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
};
//只有当对象的hashcode相同时,才会执行equals
public boolean equals(Object obj) {
System.out.println("===");
//Object obj = s4;
if(this==obj){//同一个人
return true;
}
if(!(obj instanceof Student)){
throw new RuntimeException("类型不匹配");
}
Student s = (Student)obj;
return this.name == s.name && this.age == s.age;
}
// 重写方法,建立学生的自然排序
// 按照学生对象的年龄进行排序
// 注意:在比较时,必须要明确主次,主要条件相同,就是为0,继续比较次要条件,如果两个条件结果都为0,则直接返回0
@Override
public int compareTo(Object o) {
// this.age Object o
if(!(o instanceof Student)){
throw new ClassCastException("类型转换错误");
}
Student s = (Student)o;
// if(this.age>s.age){
// return 1;//当前对象如果大于参数对象,则返回正数
// }else if(this.age<s.age){
// return -1;//当前对象如果小于参数对象,则返回负数
// }else{//当前对象等于参数对象,则返回0
// return 0;
// }
// return this.age - s.age;//21 - 21 =0
// 先比较主要条件
int temp = this.age - s.age;
// if(temp==0){//主要条件相同
再比较次要条件
比较姓名
// int temp2 = this.name.compareTo(s.name);
// }
// ab bc
// 小一8 小一4
return temp==0?name.compareTo(s.name):temp;
}
}
总结
Collection:顶层接口
子接口:List:有序,带下标,可以通过下标访问元素,可以存重复
实现类:
Vector:数组
ArrayList:内部是一个数组结构,查询速度快,增删速度慢
LinkedList:内部是一个链表结构,查询速度较慢,增删速度快
数据结构:队列(先进先出)比如排队 和堆栈(先进后出)
重复:
默认根据地址判断两个对象是否是重复
可以自己建立重复的依据,重写equals
子接口:Set:不能重复,没有下标
实现类:
HashSet:哈希表
内部存储元素时会先根据hashCode算出这个对象的哈希值,
如果哈希值不同,直接存储元素
如果哈希值相同,则比较这个对象的内容(equals) ,
如果内容相同,则认为这是重复的元素,如果内容不同,则通过内部的拉链法存储元素
TreeSet: 二叉树结构
会自动对存进去的元素做自然排序
对于自定义的对象需要实现Comparable接口,重写compareTo方法,建立对象的比较大小的方式
默认的排序是根据compareTo方法所返回的int类型值决定
如果返回0,代表元素相同
如果返回负数,代表当前对象比传入参数对象小
如果返回正数,代表当前对象比传入参数对象大。
但是注意,如果是自定义对象,最好是将所有的条件都同时比较一次,
先比较主要条件,再比较次要条件。