------- android培训、java培训、期待与您交流! ----------
集合
1.面相对象语言对事物的体现的都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
2.数组虽然也可以存储对象,但长度是固定的,集合长度是可变的,
3.数组中可以存储基本数据类型,集合只能存储对象
4.集合只用于存储对象,集合长度是可变的,集合存储不同类型的对象。
5.集合框架: 因为每一个容器对数据的存储方式都有不同,
这个存储方式称之为:数据结构
Collection接口
Collection接口的有两个子接口:
List和Set,List元素有序,元素可以重复,Set元素无序,元素要求唯一。
Collection
|---->List可存放重复元素,元素存取是有序的。因为该集合体系有索引。
|---->Vector:底层的数据结构是数组,线程安全,但速度慢,已被ArrayList替代。
|---->ArrayList:底层的数据结构是数组。特点:查询速度很快。但是增删稍慢。线程不同步。
|---->LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|---->Set元素是无序(存入和取出的顺序不一定一致),元素不可以重复
|---->HashSet:底层数据结构是哈希表,是线程不安全的,不同步。
|---->TreeSet:可以对Set集合中的元素进行排序
Collection接口的功能:
1.添加
boolean add(Object obj):添加单个元素
boolean addAll(Collection c):添加多个元素
2.删除
void clear():移除所有元素
boolean remove(Object o):移除单个元素,有一个删除,就返回true
boolean removeAll(Collection c):移除多个元素
3.判断
boolean contains(Object obj):判断元素是否存在
boolean containsAll(Collection c):判断一个集合的元素是否包含在当前集合中
boolean isEmpty():判断集合是否为空
4.获取
Iterator iterator():返回集合上的一个迭代器
int size():元素个数
5.获取交集
boolean retainAll(Collection c):交集
6.集合变数组
Object[] toArray()
迭代器Iterator
迭代器是取出集合中元素的一种方式,会直接访问集合中的元素。
所以将迭代器通过内部类的形式来进行描述。
通过容器的iterator()方法获取该内部类的对象。
迭代器的方法:
boolean hasNext()判断是否还有元素可以迭代
next()返回迭代的下一个元素,获取的元素默认为Object类
注意:
1.迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)
2.迭代器的next()方法是自动向下取元素,要避免出现NoSuchElementException
3 . 迭代器的 next 方法返回值类型是 Object ,所以要记得类型转换List
可存放重复元素,元素存取是有序的。因为该集合体系有索引。
List接口功能:
1.添加元素
void add(int index, Object element):在指定位置添加指定元素
boolean addAll(index i,Collection<? extends E> c)
2.删除元素
Object remove(int index):返回并删除指定位置的元素
3.修改元素
Object set(int index, Object element):修改指定位置的元素
4.查找元素
Object get(int index):根据指定索引获取元素
List<E> subList(int fromIndex, int toIndex)返回列表中指定的fromIndex(包括)和toIndex(不包括)之间的部分视图。
int indexOf(Object o)返回此列表中第一次出现的指定元素的索引,如不包括,返回-1
ListIterator listIterator()List特有的迭代器
List特有迭代器
ListIterator<E> listIterator():返回按适当顺序在列表的元素上进行迭代的迭代器。
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。
注:ConcurrentModificationException异常是指当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常,这个地方是指在用迭代器的方法操作集合的时候,又用集合本身的方法来操作这个集合,所以抛出这个异常
在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。
该接口只能通过List集合的listIterator方法获取。例:ListIterator it = List集合名. listIterator();
List迭代器特有方法:
void add(E e) 将指定的元素插入列表(可选操作)。
boolean hasPrevious() 如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
int nextIndex() 返回对 next 的后续调用所返回元素的索引。
E previous() 返回列表中的前一个元素。
int previousIndex() 返回对 previous 的后续调用所返回元素的索引。
void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
void remove()从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
List实现类
Vector
底层的数据结构是数组,查询快,增删慢,线程同步,效率低已被ArrayList替代
Vector特有方法:
1.添加元素
void addElement(Object obj) JDK1.2 后改为了add(Object obj)
2.获取元素
Object elementAt(int index) JDK1.2后就改为了get(int index),通过角标拿元素
3.遍历元素
Enumeration elements() JDK1.2后就改为Iterator iterator()
boolean hasMoreElements() JDK1.2后就改为boolean hasNext()
Object nextElement() JDK1.2后就改为了 Object next()
Enumeration elements()
Enumeration就是枚举,枚举就是Vector特有的取出方式。此接口的功能与 Iterator 接口的功能
是重复的,Iterator接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用I
terator接口而不是Enumeration接口。
Vector取出元素示例代码:
class VectorDemo{
public static void main(String[] args){
Vector v = new Vector();
v.add("java01");//添加元素
v.add("java02");
v.add("java03");
v.add("java04");
Enumeration en = v.elements();//枚举的方式取出元素
while(en.hasMoreElements()){
System.out.println(en.nextElement());
}
}
}
Arraylist
底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
练习:去除ArrayList集合中的重复元素
思路:新建立一个集合,遍历原集合往新集合里面存,在存之前进行是否有这个元素的判断。
class ArrayListTest
{
public static void sop(Object obj){
System.out.println(obj);
}
public static void main(String[] args){
ArrayList al = new ArrayList();
al.add("java01");
al.add("java02");
al.add("java01");
al.add("java02");
al.add("java01");
al.add("java03");
al = singleElemen(al);
sop(al);
}
public static ArrayList singleElement(ArrayList al){
//定义一个临时容器。
ArrayList newAl = new ArrayList();
Iterator it = al.iterator();//使用迭代器
while(it.hasNext()){
Object obj = it.next();
if(!newAl.contains(obj))//判断是否有遍历到元素
newAl.add(obj);
}
return newAl;
}
}
LinkList
底层使用的链表数据结构。特点:增删速度很快,查询稍慢,线程不同步。
LinkList特有方法:
1.添加元素:
void addFirst(E e) 将指定元素插入此列表的开头。
void addLast(E e) 将指定元素添加到此列表的结尾。
2.获取元素:
E getFirst()返回此列表的第一个元素。
E getLast()返回此列表的最后一个元素。
3.删除元素:
E removeFirst()移除并返回此列表的第一个元素。
E removeLast()移除并返回此列表的最后一个元素。
{
public static void main(String[] args)
{
LinkedList link = new LinkedList();//创建对象
link.add("hello");//添加元素
link.add("world");
//特有方法:添加在列表开头与末尾
link.addFirst("start");
link.addLast("over");
// 获取元素
System.out.println("getFirst:" + link.getFirst());
System.out.println("getLast:" + link.getLast());
// 遍历
Iterator it = link.iterator();
while (it.hasNext())
{
String s = (String) it.next();
System.out.println(s);
}
}
}
Set 集合Set接口里面存放的是元素是无序唯一的,可以包含null。Set集合是无序的,因此只能用迭代器获取元素。Set的子类包括HashSet和TreeSet
Set集合的功能和Collection是一致的.
HashSet:
底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
练习:往hashSet集合中存入自定对象,姓名和年龄相同为同一个人,重复元素。复写hashCode和equals方法
class HashSetTest
{
public static void sop(Object obj){
System.out.println(obj);
}
public static void main(String[] args){
HashSet hs = new HashSet();
hs.add(new Person("a1",11));
hs.add(new Person("a2",12));
hs.add(new Person("a3",13));
hs.add(new Person("a2",12));//添加重复元素,会调用比较器不将此元素添加至列表
hs.add(new Person("a4",14));
Iterator it = hs.iterator();
while(it.hasNext()){
Person p = (Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}
}
class Person
{
private String name;
private int age;
Person(String name,int age){
this.name = name;
this.age = age;
}
public int hashCode(){//复写hashCode方法
System.out.println(this.name+"....hashCode");
return name.hashCode()+age*37;
}
public boolean equals(Object obj){//复写equals方法
if(!(obj instanceof Person)){
return false;
}
Person p = (Person)obj;
System.out.println(this.name+"...equals.."+p.name);
return this.name.equals(p.name) && this.age == p.age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
TreeSet
可以对Set集合中的元素进行排序,底层数据结构是二叉树。
保证元素唯一性的依据:compareTo方法
TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。这种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式,接受实现Comparator接口的子类对象
第一种方式:实现Comparable接口
class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
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;
}
public int compareTo(Person p) {
int num = p.age - this.age;
//年龄相同的时比较姓名是否相同
int num2 = (num == 0) ? this.name.compareTo(p.name) : num;
return num2;
}
} 第二种方式:接受实现Comparator接口的子类对象
TreeSet ts = new TreeSet(MyCompare);
//定义一个类,实现Comparator接口,覆盖compare方法。
class MyComart implements Comparator {
public int compare(Object o1,Object o2){ //覆盖compare方法
Student s1 = (Student)o1;
Student s2 = (Student)o2;
int num = s1.getName().compareTo(s2.getName());
if(num==0){
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
//比较年龄因为Intege已经具有比较性了.直接比就可以
/*
if(s1.getAge()>s2.getAge())
return 1;
if(s1.getAge()==s2.getAge())
return 0;
return -1;
*/
}
return num;
}
}
注:当元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身具备比较性,定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。当两种排序都存在时,以比较器为主。
//为了以后方便可能存进去TreeSet集合中去实现Comparable.将学生具备比较性
//如果穿进去不的不是学生类.抛异常
}
//穿件Map集合中的 HashMap集合
//往里面添加键值对.将学生作为键.住址作为值
//定义一个比较器类,将其对象作为参数传递给集合
//字符串本身具有比较性
//Integer是因为age是基本数据类型不具备比较.要转成Integer来实现compareTo方法
}
代码如下:
//数组中的元素都是基本数据类型,那么会将该数组作为集合中的一个元素存在,[[I@1fb8ee3]