您的位置:首页 > 编程语言 > Java开发

java基础-API-集合框架-Collection

2015-08-23 20:36 666 查看
一、集合体系概述

1、为什么出现集合类?

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

2、数组和集合类同是容器,有何不同?

数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。

集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

3、集合类的特点

集合中存储的都是对象的引用(地址)。

4、集合框架



为什么会出现这么多容器?
因为每一个容器对数据的存储方式不同。存储方式称之为:数据结构

Collection是集合框架中的根接口。其下有两个常用子接口:List(列表),Set(集)。
所属关系:Collection
|--List //元素是有序的,元素可以重复。因为该集合体系有索引。

|--Set //元素是无序的,元素不可以重复。

二、Collection的共性方法

1、添加元素

add(Object obj); //add方法的参数类型是Object。以便于接收任意类型对象。

2、获取个数,集合长度

size();

3、删除元素

remove(Object obj);

clear();//清空集合

4、判断元素

contains(Object obj);//判断是否存在obj这个元素

isEmpty();//是否为空

5、取交集

retainAll(另一集合);//调用者只保留两集合的共性元素。

6、获取元素
迭代器:Iterator--其实就是集合的取出元素的方式。
方法:hasNext();//如果仍有元素可以迭代,返回true。

next();//返回迭代的下一个元素。

remove();//移除最后一个元素。

方式一: Iterator it = al2.iterator();//获取迭代器,用于取出集合中的元素。 while (it.hasNext()) { sop("al2:"+it.next()); }
方式二: for (Iterator it = al2.iterator(); it.hasNext(); )
{
sop("al2:"+it.next());
}
注意:在迭代式循环中next调用一次,就要hasNext判断一次。

代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
1,add方法的参数类型是Object。以便于接收任意类型对象。
2,集合中存储的都是对象的引用(地址)。
3,迭代器:其实就是集合的取出元素的方式。
*/
classCollectionDemo
{
publicstaticvoid main(String[] args)
{
//创建一个集合容器。使用Collection接口的子类。ArrayList
ArrayList al1 =newArrayList();
ArrayList al2 =newArrayList();

//1、添加元素。
al1.add("java01");//add(Object obj);
al1.add("java02");
al1.add("java03");
al1.add("java04");

al2.add("java01");//add(Object obj);
al2.add("java02");
al2.add("java05");
al2.add("java06");

//打印集合
sop("原集合al1:"+al1);

//2、获取个数。集合长度。
sop("al1:size = "+al1.size());

//3、删除元素
al1.remove("java03");

//al.clear();//清空集合。
sop("新集合al1:"+al1);

//4、判断元素。
sop("java01是否存在于al1:"+al1.contains("java01"));
sop("al1集合是否为空:"+al1.isEmpty());

//5、取交集。al1中只会保留al2中相同的元素。
al1.retainAll(al2);
//al1.removeAll(al2);
sop("al2"+al2);
sop("al1与al2取交集后的al1:"+al1);

//获取元素
Iterator it = al2.iterator();//获取迭代器,用于取出集合中的元素。
while(it.hasNext())
{
sop("al2:"+it.next());
}
/*for (Iterator it = al2.iterator(); it.hasNext(); )
{
sop("al2:"+it.next());
}*/
}

publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>


运行结果:



三、List

1、 List:元素是有序的,元素可以重复。因为该集合体系有索引。

|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。

|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。

|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。

2、List特有方法:凡是可以操作角标的方法都是该体系特有的方法。

a.增:add(index,element);

b.删:remove(index);

c.改:set(index,element);

d.查:get(index);

subList(from,to);
listIterator();
ListIterator:List集合特有的迭代器,是Iterator的子接口

ListIterator特有的方法:

add(obj);//增加

set(obj);//修改为obj

hasPrevious();//判断前面有没有元素

previous();//取前一个元素
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">/*
Collection
|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--Set:元素是无序的,元素不可以重复。因为该集合体系没有索引。
List:
特有方法:凡是可以操作角标的方法都是该体系特有的方法。

增:add(index,element);
add(index,Collection);

删:remove(index);

改:set(index,element);

查:get(index);
subList(from,to);
listIterator();

List集合特有的迭代器:ListIterator是Iterator的子接口
ListIterator特有的方法:
add(obj);//增加
set(obj);//修改
hasPrevious();//判断前面有没有元素
previous();//取前一个元素
*/
import java.util.*;
classListDemo
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();

//添加元素。
al.add("java01");//add(Object obj);
al.add("java02");
al.add("java03");

//打印集合
sop("原集合al:"+al);

//在指定位置添加元素
al.add(1,"java08");
sop("在指定位置1添加元素:"+al);

//删除指定位置元素
al.remove(2);
sop("删除指定位置2元素:"+al);

//修改指定位置元素。
al.set(2,"java05");
sop("修改指定位置2元素:"+al);

//通过角标获取元素
sop("通过角标获取元素get(1):"+al.get(1));

//通过角标遍历所有元素
sop("遍历获取所有元素:");
for(int x=0; x<al.size(); x++)
{
sop("al("+x+")="+al.get(x));
}
//通过indexOf获取对象的位置
sop("index="+al.indexOf("java05"));

//返回子列表
List sub  = al.subList(1,3);
sop("sub="+sub);

//演示列表迭代器
Iterator it = al.iterator();
while(it.hasNext())
{
//sop("al:"+it.next());
Object obj = it.next();
if(obj.equals("java01"))
//al.add("java009");//发生ConcurrentModificationException异常。
it.remove();//Iterator方法有限,只有hasNext(); next(); remove();方法
}
sop(al);
//如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。该接口只能通过List集合的ListIterator方法获取。
ListIterator li = al.listIterator();
while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("java05"))
li.add("java09");//添加
}
sop(al);
while(li.hasPrevious())//向前逆向遍历
{
Object obj = li.previous();//取前一个元素
if(obj.equals("java09"))
li.set("java0007");//修改
}
sop(al);

}

publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>


运行结果:



3、ArrayList
ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。

例:去除ArrayList集合中的重复元素。
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
去除ArrayListTest集合中的重复元素
*/
classArrayListTest
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();

//添加元素。
al.add("java01");//add(Object obj);
al.add("java02");
al.add("java02");
al.add("java03");
al.add("java03");
sop(al);
al = singleElement(al);
sop(al);
}

publicstaticArrayList singleElement(ArrayList al)
{
//定义一个临时容器
ArrayList newAl =newArrayList();

Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(!newAl.contains(obj))
{
newAl.add(obj);
}
}
return newAl;
}

publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>


运行结果:



例:将自定义对象作为元素存到ArrayList集合中,并去除重复元素。如存人对象,同姓名同年龄视为同一个人。
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
将自定义对象作为元素存到ArrayList集合中,并去除重复元素。如存人对象,同姓名同年龄视为同一个人
List集合判断元素是否相同,依据是元素的equals方法。
contains 底层调用的是equals方法,所以要重写equals方法。
*/

classPerson
{
privateString name;
privateint age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
publicboolean equals(Object obj)
{
if(!(obj instanceofPerson))
returnfalse;
Person p =(Person)obj;
//System.out.println(this.name+"..."+p.name);
returnthis.name.equals(p.name)&&this.age == p.age;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classArrayListTest1
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();

al.add(newPerson("lisi01",11));//al.add(Object obj);//Object obj = new Person("lisi01",11);
al.add(newPerson("lisi02",12));
al.add(newPerson("lisi02",12));
al.add(newPerson("lisi03",13));
al.add(newPerson("lisi04",14));
al.add(newPerson("lisi04",14));
sop("原ArrayList集合:");
printAl(al);
al = singleElement(al);
sop("新ArrayList集合:");
printAl(al);
}

publicstaticvoid printAl(ArrayList al)
{
Iterator it = al.iterator();
while(it.hasNext())
{
//Object obj = it.next();
Person p =(Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}

publicstaticArrayList singleElement(ArrayList al)
{
//定义一个临时容器
ArrayList newAl =newArrayList();

Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(!newAl.contains(obj))
{
newAl.add(obj);
}
}
return newAl;
}

publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>


运行结果:



4、LinkedList
LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
LinkedList特有方法:
在JDK1.6以后,出现了替代方法。

addFirst(); offFirst();
addLast(); offLast();

getFirst(); peekFirst();
getLast(); peekLast();

获取元素,但不删除元素。 获取元素,但不删除元素。
如果集合中没有元素, 如果集合中没有元素,
会出现NoSuchElementException。 会返回null。

removeFirst(); pollFirst();
removeLast(); pollLast();
获取元素,并删除元素。 获取元素,并删除元素。
如果集合中没有元素 如果集合中没有元素,
会出现NoSuchElementException。 会返回null。

例: 使用LinkedList模拟一个堆栈或者队列数据结构。
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
使用LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出  如同一个杯子。
队列:先进先出 First in First out  FIFO 如同一个水管。

*/
classDuiLie
{
privateLinkedList link;
DuiLie()
{
link =newLinkedList();
}
publicvoid myAdd(Object obj)
{
link.addFirst(obj);
}
publicObject myGet()
{
return link.removeLast();//return link.removeFirst();就是堆栈
}
publicboolean isNull()
{
return link.isEmpty();
}

}
classLinkedListDemo
{
publicstaticvoid main(String[] args)
{
DuiLie dl =newDuiLie();

dl.myAdd("java01");
dl.myAdd("java02");
dl.myAdd("java03");
dl.myAdd("java04");
while(!dl.isNull())
{
sop(dl.myGet());
}
}

publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}<span style="font-family: 'Microsoft YaHei'; color: rgb(190, 190, 197);"> </span></span>


5、Vector
Vector:底层是数组数据结构。线程同步。被ArrayList替代了。

例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
枚举就是Vector特有的取出方式
*/
classVectorDemo
{
publicstaticvoid main(String[] args)
{
Vector v =newVector();

v.add("java01");
v.add("java02");
v.add("java03");
v.add("java04");

Enumeration en = v.elements();
while(en.hasMoreElements())
{
System.out.println(en.nextElement());
}
}
}</span>


运行结果:



四、Set

1、Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。

|--HashSet:底层数据结构是哈希表。线程不同步。保证元素唯一性的依据:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。
|--TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0。

2、Set集合的功能和Collection是一致的。

3、HashSet
HashSet:底层数据结构是哈希表。线程不同步。
保证元素唯一性的依据:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。

注意:对于判断元素是否存在contains,以及删除remove等操作,依赖的方法是元素的hashcode和equals方法。

代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
将自定义对象作为元素存到HashSet集合中,并去除重复元素。如存人对象,同姓名同年龄视为同一个人
保证元素唯一性的依据:判断元素的hashCode值是否相同。
如果相同,还会继续判断元素的equals方法,是否为true。
注意:对于判断元素是否存在contains,以及删除remove等操作,依赖的方法是元素的hashcode和equals方法。
*/

classPerson
{
privateString name;
privateint age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
publicint hashCode()//重写hashcode
{
System.out.println(this.name+"...hashcode");
return name.hashCode()+age*39;
}
publicboolean equals(Object obj)//重写equals
{
if(!(obj instanceofPerson))
returnfalse;
Person p =(Person)obj;
System.out.println(this.name+"..."+p.name);
returnthis.name.equals(p.name)&&this.age == p.age;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classHashSetDemo
{
publicstaticvoid main(String[] args)
{
HashSet hs =newHashSet();

hs.add(newPerson("a1",11));
hs.add(newPerson("a2",12));
hs.add(newPerson("a3",13));
hs.add(newPerson("a2",12));

sop("a1:"+hs.contains(newPerson("a1",11)));
sop("a3:"+hs.remove(newPerson("a3",13)));

Iterator it = hs.iterator();
while(it.hasNext())
{
Person p =(Person)it.next();
sop(p.getName()+"::"+p.getAge());
}

}

publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>


4、TreeSet
TreeSet:底层数据结构是二叉树。可以对Set集合中的元素进行排序。默认按照字母的自然排序。
保证元素唯一性的依据:compareTo方法return 0。
二叉树:



TreeSet排序的两种方式

1)第一种排序方式:自然排序

让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。

2)第二种方式:比较器

当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。

在集合初始化时,就有了比较方式。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

比较器构造方式:定义一个类,实现Comparator接口,覆盖compare方法。

当两种排序都存在时,以比较器为主。
代码示例:

<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
往TreeSet集合中存储自定义对象学生,并按照学生年龄进行排序。
排序时,当主要条件相同时,一定要判断一下次要条件。
*/
classStudentimplementsComparable//该接口强制让学生具备比较性
{
privateString name;
privateint age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
publicint compareTo(Object obj)//若想怎么存怎么取,只需返回1;倒序则返回-1即可。
{
if(!(obj instanceofStudent))
thrownewRuntimeException("不是学生对象");
Student s =(Student)obj;

//System.out.println(this.name+"...compareto"+s.name);
if(this.age>s.age)
return1;
if(this.age==s.age)
{
returnthis.name.compareTo(s.name);
}
return-1;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classTreeSetDemo
{
publicstaticvoid main(String[] args)
{
TreeSet ts =newTreeSet();

ts.add(newStudent("lisi02",22));
ts.add(newStudent("lisi07",20));
ts.add(newStudent("lisi09",19));
ts.add(newStudent("lisi08",19));
ts.add(newStudent("lisi08",19));

Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu =(Student)it.next();
sop(stu.getName()+"::"+stu.getAge());
}
}

publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}

classMyCompareimplementsComparator//构造比较器
{
publicint compare(Object o1,Object o2)
{
Student s1 =(Student)o1;
Student s2 =(Student)o2;

int num = s1.getName().compareTo(s2.getName());
if(num==0)
{
return  s1.getAge()- s2.getAge();
}
return num;
}
}</span>


例:按照字符串长度排序

<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
//按照字符串长度排序
classTreeSetTest
{
publicstaticvoid main(String[] args)
{
TreeSet ts =newTreeSet(newStrLenComparator());
ts.add("abd");
ts.add("cc");
ts.add("z");
ts.add("hahaha");
ts.add("zdf");

Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}

classStrLenComparatorimplementsComparator
{
publicint compare(Object o1,Object o2)
{
String s1 =(String)o1;
String s2 =(String)o2;
int num =newInteger(s1.length()).compareTo(newInteger(s2.length()));
if(num ==0)
return s1.compareTo(s2);
return num;

}
}</span>


运行结果:



五、泛型

1、泛型概述
泛型:JDK1.5版本以后出现的新特性。用于解决安全问题,是一个类型安全机制。
泛型格式: 通过<>来定义要操作的引用数据类型

好处:
a、将运行时期出现的问题ClassCastException,转移到了编译时期。方便于程序员解决问题。让运行时期的问题减少,安全。
b、避免了强制转化麻烦。

2、泛型使用
在使用java提供的对象时,什么时候写泛型呢?

通常在集合框架中很常见,只要见到<>就要定义泛型。
其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
泛型:JDK1.5版本以后出现的新特性。用于解决安全问题,是一个类型安全机制。
好处:
1,将运行时期出现的问题ClassCastException,转移到了编译时期。方便于程序员解决问题。让运行时期的问题减少,安全。
2,避免了强制转化麻烦。
*/
classGenericDemo
{
publicstaticvoid main(String[] args)
{
ArrayList<String> al =newArrayList<String>();//当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

al.add("abc01");
al.add("abc002");
al.add("abc0003");
//al.add(4);//编译通过,运行出现ClassCastException

Iterator<String> it = al.iterator();//当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
while(it.hasNext())
{
//String s = (String)it.next();//避免了强制转化麻烦。
String s = it.next();
System.out.println(s+"::"+s.length());
}
}
}</span>


运行结果:



运行结果中注意:使用了未经检查或不安全的操作的信息不见了。

3、泛型类、泛型方法、泛型接口
a.什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,
早期定义Object来完成扩展。现在定义泛型来完成扩展。
泛型类定义的泛型,在整个类中有效。在泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
b.为了让不同方法可以操作不同类型,而且类型还不确定。
那么可以将泛型定义在方法上。
c.特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">classDemo<T>//泛型类
{
publicvoid show(T t)
{
System.out.println("class show:"+t);
}
public<T>void print(T t)//泛型方法
{
System.out.println("function print:"+t);
}
publicstatic<T>void method(T t)//静态方法泛型
{
System.out.println("static method:"+t);
}
}

interfaceInter<T>//泛型接口
{
void show(T t);
}

classInterImpl<T>implementsInter<T>//泛型接口
{
publicvoid show(T t)
{
System.out.println("interface show:"+t);
}
}

classGenericDemo1
{
publicstaticvoid main(String[] args)
{
Demo<String> d =newDemo<String>();
Demo<Integer> d1 =newDemo<Integer>();

d.show("haha");
d1.show(0);
d.print("hehe");
d.print(newInteger(4));
d.method("heihei");
d.method(8);

InterImpl<String> i =newInterImpl<String>();
i.show("hiahia");
InterImpl<Integer> i1 =newInterImpl<Integer>();
i1.show(12);
}
}<span style="font-family: 'Microsoft YaHei'; color: rgb(190, 190, 197);"> </span></span>


运行结果:



4、泛型限定
?:通配符。也可以理解为占位符。
泛型的限定:
? extends E:可以接收E类型或E的子类型。上限。
?super E:可以接收E类型或E的父类型。下限。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;

classGenericDemo2
{
publicstaticvoid main(String[] args)
{
ArrayList<Person> al =newArrayList<Person>();
al.add(newPerson("abc01"));
al.add(newPerson("abc002"));
al.add(newPerson("abc0003"));

ArrayList<Student> al1 =newArrayList<Student>();
al1.add(newStudent("abc---01"));
al1.add(newStudent("abc---002"));
al1.add(newStudent("abc---0003"));

printColl(al);
printColl(al1);

}
publicstaticvoid printColl(ArrayList<?extendsPerson> al)
{
Iterator<?extendsPerson> it = al.iterator();
while(it.hasNext())
{
System.out.println( it.next().getName());
}
}

}

classPerson
{
privateString name;
Person(String name)
{
this.name = name;
}
publicString getName()
{
return name;
}
}

classStudentextendsPerson
{
Student(String name)
{
super(name);
}
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: