2018.4.19
set
---| Set 接口 无序 不可重复
特有方法: 无
public class Demo1 {
public static void main(String[] args) {
Set set = new HashSet();
set.add("1");
set.add("2");
set.add("3");
set.add("4");
set.add("5");
//输出无序
// set.add("5");添加不上
System.out.println(set);
}
}
结果:
[3, 2, 1, 5, 4]
HashSet
---| Set 接口 无序 不可重复
------| HashSet
底层维护的是一个【哈希表--桶式结构(任意元素都可以放)】,存储效率
------| TreeSet
【发现】: 1.添加元素的时候每一次都会调用HashCode方法。 2.重写equals方法和hashCode方法,也是首先调用hashCode方法再来调用equals方法
hashSet存储原理:【背下来】 向hashSet集合中添加元素,hashSet首先会调用该元素的hashCode方法 获取该对象Hash值 通过【移位运算】计算出该元素应该保存在【hash】表中的哪一个位置。
情况1:
该位置没有任何元素。直接放入。
情况2:
该位置存在其他元素,hash表就会调用该元素的equals方法和已经保存在hash表里面的元素进行比较。
如果比较结果为TRUE表示相当元素无法添加。如果比较结果为false表示为不同元素可以添加。
哈希表的每一个单元格都是桶式结构,可以保存多个元素,允许元素共存。
class Student {
int id;
String name;
public Student() {}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object obj) {
System.out.println("equals方法");
Student student = (Student) obj;
System.out.println(this.name+"和"+student.name+"比较!!");
return this.name.equals(student.name);
}
@Override
public int hashCode() {//计算获取该元素应该在哈希表中的位置的方法。 是一种移位运算 右移16位经过一系列运算 是唯一值。
System.out.println("HashCode方法");
return this.id;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "[ID:"+ id+" name:"+name+"]";
}
}
public class Demo2 {
public static void main(String[] args) {
/*
HashSet set = new HashSet();
set.add("二哥");
set.add("伟哥");
set.add("光耀");
set.add("骚翔");
set.add("越南");
set.add("子逊");
set.add("子逊");
System.out.println(set);
*/
HashSet set = new HashSet();
set.add(new Student(1, "卢子逊"));
set.add(new Student(2, "二哥"));
set.add(new Student(3, "光耀"));
set.add(new Student(4, "魏翔"));
set.add(new Student(5, "李伟"));
set.add(new Student(5,"G仔"));
System.out.println(set);
}
}
结果:
HashCode方法
HashCode方法
HashCode方法
HashCode方法
HashCode方法
HashCode方法
equals方法
G仔和李伟比较!!
[[ID:1 name:卢子逊], [ID:2 name:二哥], [ID:3 name:光耀], [ID:4 name:魏翔], [ID:5 name:G仔], [ID:5 name:李伟]]
TreeSet
TreeSet是一个树型结构的set结构。
发现:
TreeSet中添加元素原本是字符串类型,当添加自定义对象,或者数字的时候,报异常!!
ClassCastException
原因:
因为TreeSet是一个树型结构,所有的元素都需要进行比较之后才可以放到set集合中,
而字符串和自定义类对象是没有比较的方式和方法的。
【要求】在TreeSet里面的所有的元素都要有比较的方式或者有【自然顺序】。
TreeSet添加自定义元素的方式:
方式1:
让这个自定义类【遵从】Comparable接口,是先ComparaTo方法
方式2:
自定义比较器,这个表扣机器是【遵从】comparator接口,实现
int compare(object o1, object o2);
可以在创建TreeSet对象的时候,传入比较器对象作为比较方式。
class Person implements Comparable<Person> {
int id;
String name;
int salary;
public Person() {}
public Person(int id, String name, int salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
/*
@Override
public int compareTo(Object o) {
返回值有三种: 0 正整数 负整数
0 表示相同
正整数 【表示调用这个方法的对象】大于传值的对象
负整数 【表示调用这个方法的对象】小于传值的对象
//以工资为标准进行判断
System.out.println("这里是类内的比较方式");
Person person =(Person) o;
return this.salary - person.salary;
}
*/
@Override
public String toString() {
return "ID:"+id+" name:"+name+" salary:"+ salary+"]";
}
@Override
public int compareTo(Person o) {
return this.salary - o.salary;
}
}
class MyCompare implements Comparator {
@Override
public int compare(Object o1, Object o2) {
System.out.println("自定义比较器");
Person p1 = (Person) o1;
Person p2 = (Person) o2;
return p1.salary - p2.salary;
}
}
public class Demo1 {
public static void main(String[] args) {
//创建TreeSet的时候,传入自定义比较器对象
TreeSet set = new TreeSet(new MyCompare());
//TreeSet set = new TreeSet();
//set.add(1);//lang.String cannot be cast to java.lang.Integer
set.add(new Person(1,"卢子逊",3000));//com.biteware.treeSet.Person cannot be cast to java.lang.Comparable
set.add(new Person(2,"骚逊",3100));
set.add(new Person(3,"魏翔",3200));
set.add(new Person(4,"李伟",3200));
set.add(new Person(5,"光耀",3300));
System.out.println(set);
}
}
结果:
自定义比较器
自定义比较器
自定义比较器
自定义比较器
自定义比较器
自定义比较器
自定义比较器
自定义比较器
[ID:1 name:卢子逊 salary:3000], ID:2 name:骚逊 salary:3100], ID:3 name:魏翔 salary:3200], ID:5 name:光耀 salary:3300]]
总结
ArrayList底层维护的是一个Object类型的数组,使用无参构造方法,创建一个ArrayList集合对象
默认的元素个数为10
特征:
查询快,增删慢。
查询快:
使用的是数组的下标访问方式,可以直达目标位置。
增删慢:
增加,有可能会触发数组的扩容机制,会创建一个新的数组元素个数大约是原数组的1.5倍
然后会有一个数组拷贝的过程,这个过程是将原数组里面的每一个元素挨个
复制的新数组中。这个操作消耗大量的时间和空间。
删除,是从object数组中删除一个元素,删除之后,后面元素会向前移动,移动的过程是一个
复制的过程,这个操作比较浪费时间
增加的原理是:
newCapacity = oldCapacity + (oldCapacity >> 1);
LinkedList:
底层维护的是一个链表 (数据结构)
增删快,查找慢
Vectior 线程安全,效率较低的Arraylist jdk1.0 (不考虑使用)
HashSet
底层维护的是一个哈希表。存储效率极高
存储原理:
调用存入对象的hashCode方法,获取到该对象的hashCode的值,通过【移位运算】
计算该对象应该放到哈希表的那一个位置
情况1:
该位置没有任何元素,直接添加。
情况2:
该位置存在其他元素,这时候会调用对象的equals方法,和在该位置保存的其他元素
进行一一比较,如果所有的比较结果都为false,表示不相同,可以添加
如果出现任何一个true,表示和该位置其他的元素相同,不能添加。
TreeSet
存入TreeSet的元素必须有自然顺序或者存在比较方式
自定义类对象,想要放入到TreeSet集合中,有两种方式:
1.该自定义类【遵从】Comparable接口,实现compareTo(object o)
2.给TreeSet提供自己定义比较器,创建自定义比较器需要【遵从】
Comparator接口实现Compare(Object o1,object o2);