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; } }