-------android培训、java培训、期待与您交流! ----------
集合:
集合的特点:
1,用于存储对象的容器。
2,该容器的长度是可变的。
集合的功能:
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行(存储,遍历,修改),集合就是存储对象最常用的一种方式。
集合框架的由来:
集合就是一个容器,而容器有很多,因为每个容器中的数据结构是不同的。但是都具备着共性,可以向上不断的抽取,这样就形成了集合框架。
集合和数组的区别:
1,集合的长度是可变的。
数组的长度是固定的。
2,集合只能存储对象。
数组既可以存储对象,又可以存储基本类型数值。
3,集合中存储的对象可以使任意类型的。
数组中只能存储同一类型的对象。
集合框架的构成与分类:
Collection:
Collection中常见方法:
1,添加方法。
boolean add(object e):一次添加一个元素。
boolean addAll(Collection):将一个参数容器中的元素添加到当前容器中。
2,删除方法。
boolean remove(object):删除一个指定对象。
boolean removeAll(Collection):删除指定collection中和本Collection中相同的元素。
void clear():直接将集合中的元素清空。
3,判断方法:
boolean contains(object):是否包含指定元素。
boolean containsAll(Collection):是否包含指定容器中的元素。
boolean isEmpty():是否有元素。
4,获取元素个数:
int size():获取元素有几个。
5,取交集。
boolean retainAll(collection):保留和指定collection集合中相同的元素,不相同的元素会被删除。
6,将集合转成数组。
Object[] toArray():
7,取出元素的方法:
Iterator iterator():
迭代器的好处:将容器的取出方式和容器的数据结构相分离,降低了耦合性。
而取出方式因为直接在访问容器中的元素,并依赖具体的数据结构所以被定义在了容器中。
通过内部类来实现Iterator接口。
代码演示:
public static void collDemo(){
Collection coll = new ArrayList();
//添加元素
coll.add("java");
coll.add("csdn");
coll.add("itcast");
coll.add(".net");
//删除元素
coll.remove(".net");
//判断是否包含
coll.contains("csdn");
//获取元素个数
int count = coll.size();
//将集合转数组
Object[] arr = coll.toArray();
}
取出元素:
Iterator it = coll.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
//实际开发中建议建议将while循环改为for循环,因为for循环创建的对象it在循环结束会被释放可以节省空间
for(Iterator it = coll.iterator();it.hasNext(); ){
System.out.println(it.next());
}
迭代器注意事项:
迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。
迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
迭代器的next方法返回值类型是Object,所以要记得类型转换。
List集合:
|--List:元素是有序的,元素可以重复,因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,但增删稍慢。注意:此线程是不同步的
它的初始容量为10,当数组超过10时,它会new一个新的数组,其长度增加50%。
|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,但查询稍慢。
|--Vector:底层是数组数据结构。 从JDK1.0开始出现,当升级到JDK1.2之后开始用List接口。注意:此线程是
同步的。 被ArrayList替代了。
它的初始容量为10,当数组超过10时,它会new一个新的数组,其长度增加100%。
可变长度数组原理:一旦原数组长度不够,会创建新数组,将原数组的元素复制到新数组中,并将新元素添加到新数组中。
枚举就是Vector特有的取出方式
List集合特有方法,凡是可以操作角标的方法都是该体系特有的方法。
增
add(index,element);
addAll(index,Collection);
删
remove(index);
改
set(index,element);
查
get(index);
subList(from,to);
listIterator();
List集合特有的迭代器:ListIterator是Iterator的子接口
在迭代时不可以通过集合的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。
所以在迭代时只能用迭代器的方法操作元素,可是Iterator方法是有局限性的,只能对元素
进行判断,取出,删除的操作。如果想要其他的操作,如,添加,修改等就需要使用其子接口ListIterator,
该接口只能通过List集合的ListIterator方法获取
往List集合中存储自定义对象
1,对自定义对象进行描述。
2,存储时,都被提升为了Object。
3, 取出时如果要使用自定义对象的特有方法,一定要进行向下转型。
4,注意事项:在迭代时,循环中只要有一个next()即可。
例如:
public static void listDemo {
Collection coll = new ArrayList();
coll.add(new Person("lisi1",21));
coll.add(new Person("lisi2",22));
coll.add(new Person("lisi3",23));
coll.add(new Person("lisi4",24));
coll.add(new Person("lisi5",25));
Iterator it = coll.iterator();
while(it.hasNext()){
Person p = (Person)it.next();//向下转型
//只获取姓名或年龄
System.out.println(p.getName());
//同时获取姓名和年龄
System.out.println(p.getName()+":"+p.getAge());//注意在迭代时循环中只要有一个next即可
}
}
注意:ArrayList判断是否相同使用的是equals方法。
比如contains就是依赖于equals方法,或者remove方法也是依赖于equals方法。
尤其是在存储自定义对象时,因为默认比较的是地址值,所以该对象一定要覆盖equals方法,建立根据对象自身特点的判断相同的依据。
equals方法就是用于比较对象内容的。
LinkedList特点:可以在集合开始或者结尾处添加或删除元素,
用到方法:addFirst(E e);从开头添加元素
addLast(E e);
removeFirst();从开头删除元素
removeLast();
例如:
public static void LinkedListDemo(){
LinkedList link = new LinkedList();
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
link.removeLast();
Iterator it = link.iterator();
while(it.hasNext){
System.out.println(it.next());
}
}
集合一些小细节。
创建一个集合容器。其实也是一个对象。
这个对象中存储着特定结构可以对对象进行存储。
Collection coll = new ArrayList();
1,存储时,add可以接收任意类型的对象因为参数类型是Object。
所以对象元素存入时都被提升为了Object。
2,其实在集合中真正存储都是对象的引用。
coll.add(new Object());
coll.add("abc");
用迭代器取出时,其实取出的也是引用。
coll.add(5);//这样写可以。因为jdk1.5后,有了自动装箱机制。相当于new Integer(5).装箱Integer.valueOf(5);
//等同于coll.add(Integer.valueOf(5));//拆箱 intValue();
Set集合:
|--Set:
|--HashSet
|--TreeSet
Set集合特点:
1,不包含重复元素。(最大的特点)
2,这个集合存入元素的顺序和取出元素的顺序不一定一致。(具体的容器对象数据结构不同,顺序也有不同)
HashSet:底层数据结构式哈希表。不保证顺序,是不同步的。
哈希表:提供数组的查询效率而出现的。
将要存储的元素先通过哈希算法算出一个哈希值来标识存储的位置,代表着元素。
要找元素时,先将该元素通过哈希算法算出哈希值,在通过哈希值到哈希表中去查找。
HashSet特点:
1,不关心元素的顺序。
2,提高了查询效率。
3,不可能出现重复元素,因为哈希值都不同。即使相同,会再次判断两个元素的equals,内容是否相同。
如果内容也相同,不存,如果内容不同,存储。
所以保证唯一性的依据就是:通过equals方法和hashCode方法来保证元素的唯一性。
首先判断hashCode()的值是否相同:如果不相同就直接添加到集合中,如果相同会继续用equals方法进行判断。如果equals判断后返回的是true说明元素重复,不添加,如果返回值是false则直接添加到集合中。
所以往哈希表中存储自定义对象必须要覆盖hashCode方法和equals方法
代码演示:
import java.util.HashSet;
import java.util.Iterator;
/*
* 存储自定义对象
*/
public class HashSetTest {
public static void main(String[] args) {
HashSet<Person> hs = new HashSet<Person>();
hs.add(new Person("lisi1",21));
hs.add(new Person("lisi2",22));
hs.add(new Person("lisi3",23));
hs.add(new Person("lisi1",21));
hs.add(new Person("lisi2",22));
Iterator<Person> it = hs.iterator();
while(it.hasNext()){
System.out.println(it.next());//为了去除重复元素,所以必须要覆盖hashCode方法,和equals方法。
}
}
}
public class Person {
private String name ;
private int age ;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
/**
* 覆盖HashCode方法,建立Person对象自身的哈希算法
*/
public int hashCode(){
return name.hashCode()+age*31;
}
/**
* 覆盖Object类中的equals方法,建立Person对象
* 判断是否相同的依据。根据Person自身特点来判断
*/
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.name.equals(p.name)&&this.age==p.age;
}
public String toString() {
return name+":"+age;
}
}
注意:对于判断元素是否存在以及删除等操作,依赖的方法是元素的hashcode和equals方法
TreeSet特点:
1,可以给Set集合中的元素进行指定顺序的排序。默认情况下,是通过元素的自然顺序排的序。
2,通过compareTo或者compare方法中的来保证元素的唯一 性。
TreeSet排序方式:
1,让元素自身具备比较性,需要实现Comparable接口,覆盖compareTo方法。这种比较方式成为自然顺序排序。
2,让容器自身具备比较性。容器一初始化就具备了比较功能。 因为容器时在对象构造时完成的。通过查阅API,有一个构造方法TreeSet(Comparator)。在容器初始化时可以指定一个比较器。 需要实现Comparator接口,覆盖compare方法即可。所以这种方式成为比较器排序。
TreeSet中如果要想输出结果的顺序和添加的一致只要实现Comparable接口,并将其中的comparaTo覆盖返回1即可,如,
public int compareTo(Object o){
return 1;
}
TreeSet两种排序方式演示:
方式一:
import java.util.HashSet;
import java.util.Iterator;
import 集合框架.been.Person;
/*
* 存储自定义对象
*/
public class HashSetTest {
public static void main(String[] args) {
HashSet<Person> hs = new HashSet<Person>();
hs.add(new Person("lisi1",21));
hs.add(new Person("lisi2",22));
hs.add(new Person("lisi3",23));
hs.add(new Person("lisi1",21));
hs.add(new Person("lisi2",22));
Iterator<Person> it = hs.iterator();
while(it.hasNext()){
System.out.println(it.next());//为了去除重复元素,所以必须要覆盖hashCode方法,和equals方法。
}
}
}
/**
* 想要Person具备比较大小功能,
* 就需要对Person对象的功能进行扩展,
* 让Person去实现Comparable接口。让Person具备自然顺序。 覆盖compareTo方法。
*/
public class Person implements Comparable<Person>{
private String name ;
private int age ;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
/**
* 覆盖HashCode方法,建立Person对象自身的哈希算法
*/
public int hashCode(){
return name.hashCode()+age*31;
}
/**
* 覆盖Object类中的equals方法,建立Person对象
* 判断是否相同的依据。根据Person自身特点来判断
*/
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.name.equals(p.name)&&this.age==p.age;
}
public String toString() {
return name+":"+age;
}
public int compareTo(Person o) {
int temp = this.age - o.age ;
return temp==0?this.name.compareTo(o.name):temp ;
}
}
方式二:
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/*
* 对字符串的长度进行排序
*/
public class TreeSetTest2 {
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<String>(new comparatorByLength());
ts.add("abcd");
ts.add("cba");
ts.add("adbe");
ts.add("nba");
ts.add("qq");
Iterator<String> it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
public class comparatorByLength implements Comparator<String> {
public int compare(String o1, String o2) {
int temp = o1.length() - o2.length();
return temp==0?o1.compareTo(o2):temp;
}
}
其实Set中有一种有序的集合就是HashSet的子类LinkedHashSet,它可以实现怎么存就怎么取。
LinkedHashSet特点:
1,底层数据结构是链表和哈希表。是有序的,元素唯一,线程不安全,效率高。它是通过链表结构保证有序,通过哈希表结构保证唯一。
2,此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
注意:插入顺序不 受在 set 中重新插入的 元素的影响。
集合的技巧掌握:
明确具体集合对象名称的后缀:
如果后缀是List,都所属于List体系。通常都是非同步的。
如果后缀是Set,都属于Set体系,通常也是非同步的。
这些体系中的其他子类对象,后缀不是所属接口名的,一般都是同步的。比如Vector。这在常用子类对象中通用。
明确数据结构:
对于jdk1.2版本的子类对象。
后缀名是所属的体系。
前缀名是就是数据结构的名称。
比如:
ArrayList: 看到Array,就要明确是数组结构。查询快。
LinkedList:看到Link,就要明确链表结构,就要想到 add get remove 和first last结合的方法.增删快。,
HashSet:看到hash,就要明确是哈希表。查询巨快,而且唯一性。就要想到元素必须覆盖 hashCode方法和equals方法。
TreeSet:看到Tree,就要明确是二叉树,可以对元素排序。就要想到两种排序方式:
自然顺序:Comparable接口,覆盖compareTo(一个参数 )java.lang
比较器:Comparator接口,覆盖compare(两个参数);java.util
判断元素唯一性的依据就是比较方法的返回结果return 0;