首先让我们看一下简单的集合框架的继承层次
collection
list(有序的容器 元素可以重复) Queue(队列) set(无序的容器就是元素不可重复)
linkedList ArrayList Vector Deque PriorityQueue EnumSet SortedSet HashSet
TreeSet
Collection(接口)是集合容器中非映射关系的容器类的根类。其中list和set 接口是最常用的接口。其中list有序指的遍历的结果与插入的顺序相同,set无序指的是插入的顺序与遍历的顺序不一定相同(因为在插入的时候,它会按照元素中ComparaTo()方法去完成排序,同时容器中的元素会按照某种关系将元素映射到一个HashMap中,这样可以实现快速遍历。)
1.ArrayList和Vector 的底层实现都是数组,可以通过下标索引来访问,这样可以提高查询效率,但是增删效率低。同时ArrayList的默认容量为10个元素,而且它的扩充容量为原来容量的(1.5倍+1)程序中的源代码为 int newCapacity = (oldCapacity * 3)/2 + 1;Vector的底层也为数组。它的默认容量也为10,但是在自动增长的时候,如果在构造函数中指定了增长的容量,则在增长的时候,它的容量会变成原来数组的容量+增长量,如果没有指定增长量,则会按照系统规定的2倍进行。所以在开发的过程当中,如果我们能估计容器中大约能盛放多少元素,我们应该在初始化的时候给他一个容量的大小。同时ArrayList是线程不安全的,Vector是线程安全的,但是ArrayList的性能比Vector的性能高。
2.LinkedList的底层实现为单链表,它查询效率低,但是增删效率高。
3.一般的遍历方式为用Iterator这个迭代器进行,这样遍历的时候效率是高的因为这样和遍历数组差不多,它是通过索引来实现的。
4.容器一般用来盛放对象的,在判断一个容器中是否包含某个对象以及在通过Equals()方法比较两个容器是否相同时,这时是根据容器中的对象元素来比较的。也就是放入容器中的对象必须实现equals()方法。
这是存放到容器中的对象定义,并且重写了Equals()方法。
public class Pet {
private String name;
private String color;
private int age;
public Pet(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "姓名:"+getName()+"颜色:"+getColor()+"年龄:"+getAge();
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(this==obj)
return true;
if((!(obj instanceof Pet)))
return false;
Pet pet=(Pet)obj;
if(this.age==pet.getAge()&&this.color.equals(pet.getColor())
&&this.name.equals(pet.getName()))
return true;
return false;
}
}
在主函数中的代码:
public class TestVector {
public static void main(String[] args) {
Pet pet0=new Pet("小白","红色",12);
Pet pet1=new Pet("小白","红色",13);
Pet pet2=new Pet("小白","红色",14);
Pet pet3=new Pet("小白","红色",16);
Pet pet4=new Pet("小白","红色",12);
ArrayList<Pet>arrayList=new ArrayList<Pet>();
arrayList.add(pet1);
arrayList.add(pet2);
arrayList.add(pet3);
arrayList.add(pet4);
boolean flag;
flag=arrayList.contains(pet0);
System.out.println("flag="+flag); //如果Pet重写了Equals()方法这时返回的是true,如果没有则会为false.因为Pet没有重写Equals()方法则会调用Object的Equals()方法。因为在比较的时候
//如果Pet没有重写Equals()则比较的是存放在数组中的地址,如果实现了则比较的是数组中元素的内容。
}
3.总结一下TreeSet 集合。
放入Treeset中的元素对象要么实现Comparable接口,要么不实现Comparable接口,在生成Treeset 容器的时候,在构造器中加入比较器。比较器相当于裁判,来实现排序作用的。TreeSet集合中元素的排序,
判断是否包含某个元素,等都是通过比较器来实现的。它的底层实现为二叉树。
下面的例子为插入到树结构的对象,是按照薪资大小,如果薪资大小一样则是按工龄大小来实现的排序。
public class Employee1 implements Comparable<Employee1>{
private int workAge;
private double salary;
public Employee1(int workAge, double salary) {
super();
this.workAge = workAge;
this.salary = salary;
}
public int getWorkAge() {
return workAge;
}
public void setWorkAge(int workAge) {
this.workAge = workAge;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [workAge=" + workAge + ", salary=" + salary + "]";
}
@Override
public int compareTo(Employee1 o) {
// TODO Auto-generated method stub
if(this.salary==o.getSalary()){
return
this.getWorkAge()-o.getWorkAge();
}else{
if(this.getSalary()>o.getSalary()){
return 1;
}else {
return -1;
}
}
}
}
public class TestTreeSet {
public static void main(String[] args) {
TreeSet employeeSet=new TreeSet();
employeeSet.add(new Employee1(34,20000.0));
employeeSet.add(new Employee1(35,20000.0));
employeeSet.add(new Employee1(35, 20000.2));
employeeSet.add(new Employee1(35,30000.0));
Iterator iterator=employeeSet.iterator();
Object obj=null;
while(iterator.hasNext()){
obj=iterator.next();
System.out.println(obj);
}
}
}
运行的结果为:
Employee [workAge=34, salary=20000.0]
Employee [workAge=35, salary=20000.0]
Employee [workAge=35, salary=20000.2]
Employee [workAge=35, salary=30000.0]
4.总结一下HashSet集合
HashSet的底层实现为HashMap,也就是说,放入集合中的元素,作为HashMap的键。由于键是唯一的,所以对应的HashSet集合也是唯一的,并且,HashMap的键值允许为空,所以集合中可以放入空元素。放入HashSet集合中的对象元素
一般重写hashCode()方法和equals()方法。重写hashCode()方法,比如在Student 类中,我们的hashCode()重写为
int hashCode()
{
return age;
}
这也就是说,年龄相同的对象元素放在同一个通中。在遍历输出的时候,在同一个桶中的元素会顺序遍历出来。就是年龄相同的对象顺序遍历出来。
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() {
return age;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
public class testHashSet {
public static void main(String[] args) {
Student s1=new Student("徐才厚",18);
Student s2=new Student("徐财厚", 18);
Student s3=new Student("旺财", 18);
Student s4=new Student("徐才厚",19);
Student s5=new Student("徐财厚", 19);
Student s6=new Student("旺财", 19);
Student s7=new Student("徐才厚",20);
Student s8=new Student("徐财厚", 20);
Student s9=new Student("旺财", 20);
Student s0=null;
HashSet<Student>hashset=new HashSet<Student>();
hashset.add(s1);
hashset.add(s2);
hashset.add(s3);
hashset.add(s4);
hashset.add(s5);
hashset.add(s6);
hashset.add(s7);
hashset.add(s8);
hashset.add(s9);
hashset.add(s0);
Iterator<Student> set=hashset.iterator();
while(set.hasNext()){
Student st=set.next();
System.out.println(st);
}
}
}
输出结果:
null
Student [name=旺财, age=19]
Student [name=徐财厚, age=19]
Student [name=徐才厚, age=19]
Student [name=旺财, age=18]
Student [name=徐财厚, age=18]
Student [name=徐才厚, age=18]
Student [name=旺财, age=20]
Student [name=徐财厚, age=20]
Student [name=徐才厚, age=20]
总结: equals方法和hashcode方法
在容器中如果调用remove,contains等方法时,这会设计到对象类型的equals()和hashcode()方法,对于自定义的类型,需要重写equals()方法和hashcode()方法,以实现自定的对象相等的规则。在Java中,俩个内容相同的对象应该具有相同的hashcode.所以如果两个对象的hashcode不相等,则两个对象的内容肯定不相等,这样就不用一个一个去比较属性值了,从而提高对象的比较速度。
有可能重写equals()方法和hashcode()方法的情况
1.要将我们自定义的对象放入HashSet中处理
2,。要将我们自定义的对象作为hashMap 的key处理。
3.放入Collection容器中的自定义对象后,可能会调用remove,contains等方法时。