List
List:有序,可重复,有索引。
|--ArrayList:底层数据结构是数组结构。线程不安全的。所以ArrayList的出现替代了Vector.
但是查询的速度很快.
|--Vector:底层数据结构是数组结构。jdk1.0版本。线程安全的。无论增删还是查询都非常慢。
|--LinkedList:底层是链表数据结构。线程不安全的,同时对元算的增删操作效率很高
可变长度的数组:
ArrayList内部封装了一个默认长度为10的数组。
当超出长度时,集合内部会自动生成一个新的数组。
将原数组中的元素复制到新数组中,在将新元素添加到新数组。
新数组到底多长呢?
ArrayList 50%延长。
Vector 100%延长。
为什么ArrayList 和LinkedList具有本身的特点
ArrayList 是连续的,添加的话,就会让数组中元素都去移动一下.
LinkedList链表直接改变链表添加:
如图:
Set集合的特点
/*
Collection
|--List:有序(存的顺序和取的顺序一致。),元可以重复,元素都有索引。
|--ArrayList:
|--LinkedList:
|--Set:无序,不可以重复元素。Set接口的方法和Collection中的方法一致。
Set接口取出元素的方法只有迭代器。
|--HashSet:底层数据结构是哈希表。哈希表这种结构,其实就是对哈希值的存储。
而且每一个对象都有自己的哈希值。因为Object类中的有一个方法hashCode方法。
如何保证元素唯一性的呢?
通过判断元素的hashCode方法,和equals方法完成的。
当hashCode值相同是,会在判断一次euqals方法的返回只是是否为true。
如果hashCode值不相同,就确定元素的哈希表中的位置,就不用在判断equals了。
当哈希表中有一个桶结构。每一个桶都有一个哈希值,当哈希值相同,但是equals为false是,
这些元素都存放一个桶里。
|--TreeSet:可以对Set集合中的元素进行排序。
数据结构是二叉树数据结构。这种结构,可以提高排序性能。
它又是如何保证元素唯一性的呢?
是根据比较方法的返回值确定的。只要返回的是0.就代表元素重复。
import java.util.*;
/*
HashSet集合是如何保证元素唯一性的?
HashSet集合保证元素唯一性,依赖的是元素的hashCode方法和euqals方法。
当元素的哈希值不同时,元素都有自己的独立位置。不需要在判断元素的equals方法,
当元素的哈希值相同时,这时元素在哈希表中位置相同,这时就需要在判断一次元素的内容是否相同。
就需要调用元素的equals方法进行一次比较。如果equals返回是true。那么视为两个元素为重复元素。
只储存一个。
如果返回是false,那么这两个元素不是重复元素,会存储在同一个哈希值上。
为了建立自定义对象判断元素是否重复的依据。
需要覆盖hashCode方法,和equals方法。
而且最好依据对象的特有条件来建立hashcode和euqals的实现。
*/
class HashSetDemo2
{
public static void main(String[] args)
{
//往HashSet集合中存储自定义对象。
HashSet hs = new HashSet();
hs.add(new Person("lisi1",21));
hs.add(new Person("lisi4",24));
hs.add(new Person("lisi2",22));
hs.add(new Person("lisi4",24));
hs.add(new Person("lisi7",27));
System.out.println("--------");
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p = (Person)it.next();
System.out.println(p.getName()+"....."+p.getAge()+"....."+p.hashCode());
}
/**/
}
}
//人对象,如果姓名,年龄相同视为同一个对象。就不进行存储了。
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public int hashCode()
{
System.out.println(this+"......hashCode");
final int NUMBER = 38;
return name.hashCode()+age*NUMBER;
//return 1;
}
/**/
public boolean equals(Object obj)
{
//System.out.println(this+"....equals...."+obj);
if(this==obj)
return true;
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.name.equals(p.name) && this.age==p.age;
/**/
//return true;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+"::"+age;
}
}
import java.util.*;
/*
当treeset集合中存储的元素不具备比较功能。
或者具备的比较功能不是所需要的。
例如:Person对象中的自然排序是按照年龄排序。
但是现在需求是想安装姓名排序。该源代码这种方式想都不要想。有这种想法就是犯罪。
该如何解决这个问题?
既然元素具备的比较方式不满足应用。
这时,可以让集合自身具备比较性。
需要集合一初始化就具备比较功能。因为要在添加元素前具备。
就需要在构造函数进行初始化。
只要将一个实现了Comparator接口的子类对象作为参数传递给TreeSet集合的构造函数即可。
这样该集合就具备了比较功能。
建议使用第二种排序方式。
总结:
TreeSet排序方式有两种。
1,让元素自身具备比较性。
其实是让元素实现Comparable接口,覆盖compareTo方法。
这称为元素的自然排序。
2,当元素自身不具备比较性,或者元素具备的比较性不是所需要的,
可以让集合自身具备比较性。
定义一个比较器:
其实就是定义一个类,实现Comparator接口。覆盖compare方法。
将Comparator接口的子类对象作为参数传递给TreeSet的构造函数。
当元素自身具备比较性,同时TreeSet集合也具备比较器,
这时以比较器为主.
到了这里,
一般在描述一个对象时,如果该对象封装了具体的数据,会出现很多这样的对象比如:员工,学生对象等.
这时就需要进行容器的存储.
那么描述该类对象时,
一定要复写几个方法.
1,hashCode()
2,equals()
3,toString()
4,最好实现Comparable接口让该类具备自然排序功能。
建立对象自身判断是否相同的依据,同时让对象具备基本的比较性。
*/
class TreeSetDemo3
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new CompareByName());
ts.add(new Person("lisi1",21));
ts.add(new Person("lisi4",29));
ts.add(new Person("lisi2",67));
ts.add(new Person("lisi8",28));
ts.add(new Person("lisi0",20));
System.out.println(ts);
}
}
//自定义一个比较器。
class CompareByName implements Comparator
{
public int compare(Object o1,Object o2)
{
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int num = p1.getName().compareTo(p2.getName());
return num==0?p1.getAge()-p2.getAge():num;
}
}
class Person implements Comparable
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
//人的自然排序是按照年龄排序
public int compareTo(Object obj)
{
Person p = (Person)obj;
int num = new Integer(this.age).compareTo(new Integer(p.age));
return num==0?this.name.compareTo(p.name):num;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+"::"+age;
}
}