黑马程序员----集合类(一)
来源:互联网 发布:js 精确倒计时 编辑:程序博客网 时间:2024/05/16 18:24
39、 集合类
1、 为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
2、 数组和集合类同时容器,有何不同?
数组虽然也可以存储对象,但是长度固定;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象
3、 集合类的特点
集合只用于存储数据,集合长度是可变的,集合可以存储不同类型的对象
数据多了用对象、对象多了用集合【编程中都是这么操作的】
4、集合框架的构成及分类
图片一pic_1.jpg
5、常用集合
图片二pic_2.jpg
40、 Collection<E>
1、 Add(E e)方法的参数是Object(默认情况,即没有使用泛型的时候)。以便于接收任意类型的对象
2、 集合中存储的都是对象的引用(地址)
3、Collection中
1、 boolean removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素。此调用返回后,collection 中将不包含任何与指定 collection 相同的元素。
2、 boolean retainAll(Collection<?> c)
仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。换句话说,移除此 collection 中未包含在指定 collection 中的所有元素。
4、什么是迭代器,其实就是集合的取出元素的方式。
对于取出这个动作,不足以用一个方法来描述(一个方法搞不定),它需要多个功能来实现,当多个功能来实现的时候,就将多个功能封装到一个对象中去。对于不同的集合,因为它们的数据结构不一样,所以这个“取出动作对象”各不相同。直接在集合内部定义一个“取出类”(也是集合中的内部类)。
图片三pic_3.jpg
举例:电玩城的大容器
容器里面放置各种玩具。不同容器玩具的排列方式不一样,而每个容器都有一个夹子,当然,夹子也各不相同。这个夹子就相当于迭代器。被封装在容器内部。外面有个摇杆,这个摇杆就提供操作夹子的方式
5、两者有何区别:
在内存上有所不同,第一种在迭代器用完之后it对象还存在,占用着内存,而第二种迭代器在for循环完成之后就不存在了,它所占的内存直接被释放掉了
方式一:Iterator it = a1.iterator();
while(it.hasNext()){
sop(it.next());
}
方式二:for(Iterator it1 = a1.iterator();it1.hasNext();)
{
sop(it.next());
}
Collection
|----List:元素是有序的,元素可以重复,因为该集合体系有索引
|----ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快,但是增删稍慢,线程不同步。
|----LinkedList:底层使用的是链表数据结构。特点:增删速度快,查询稍慢
|----Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
|----Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
|----HashSet:底层数据结构是哈希表。
HashSet是如何保证元素唯一性呢?
是通过元素的两个方法,hashCode和equals来完成
如果元素的HashCode值相同,才会判断equals是否为true
如果元素的HashCode值不同,不会调用equals
注意:对于判断元素是否存在,以及删除操作,依赖的方法时元素的hashCode和equals方法。
|----TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树
保证元素唯一性的依据:compareTo方法return 0.
TreeSet排序的第一种方式:
让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法,这种方式也称为元素的自然排序,或者叫默认排序。
TreeSet排序的第二种方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让容器自身(集合)具备比较性。自定义比较器(定义一个类实现Comparator接口,覆盖compare方法),将之作为参数传递给TreeSet的构造方法,这样在TreeSet集合初始化时,就有了比较方式。
当两种排序都存在时,以比较器为主。
Set集合的功能和Collection是一致的
41、 List
特有方法:凡是可以操作角标的方法都是该体系特有的方法
增:add(index,element)
addAll(index,Collection)
删:remove(index)
改:set(index,element)
查:get(index);subList(from,to);
listIterator();
List集合特有的迭代器,ListIterator是Iterator的子接口。在迭代时不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法时有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作如添加、修改等,就需要使用子接口,ListIterator。该接口(ListIterator)只能通过List集合的listIterator方法获取。
示例代码:
package day28;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
publicclass ListDemo {
publicstaticvoid method(){
ArrayList a1 =newArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java03");
sop("a1:"+a1);
//在指定为置添加元素。
a1.add(1,"java09");
//删除指定位置的元素
//a1.remove(2);
//修改元素
a1.set(2,"007");
//通过角标获取元素
sop("get(1)"+a1.get(1));
//获取所有元素
for(int x=0;x<a1.size();x++){
sop("a1("+x+")"+a1.get(x));
}
for(Iterator it = a1.iterator();it.hasNext();){
sop("next"+it.next());
}
sop("a1:"+a1);
//通过indexOf获取对象的位置,如果对象不存在放回-1
sop("index="+a1.indexOf("java"));
//不包括角标位置为3的元素
List sub = a1.subList(1,3);
sop("sub="+sub);
}
publicstaticvoid iterator(){
//演示迭代器
ArrayList a1 =newArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java03");
//在迭代的过程中,准备添加或者删除元素
/* ConcurrentModificationException
*当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
* */
/**
*对整个程序的理解:
*a1添加了三个元素,而it迭代器也有三个元素,你再加新的一个迭代器不知道
*再删一个更麻烦,迭代器本来认为有,而你给它删了,取不着,这就是一个问题?!
*解决问题的办法:要么全部用集合的方法;要么用迭代器的方法
*
* */
//相当于将元素的引用放入到迭代器中,现在能操作元素的方法有两种,
//要么可以用集合的方法操作,要么用迭代器的方法操作,可是这两种操作
//的都是同一个元素。不能对同一组元素同时进行多种不同的操作,有可能
//引发并发修改异常(你在取,我在加,你到底去不去,搞不清楚)
Iterator it = a1.iterator();
while(it.hasNext()){
Object obj = it.next();
if(obj.equals("java01")){
//a1.add("java008");//添加的动作,迭代器做不了
it.remove();//将java01的引用从集合中删除
}
sop("obj:"+obj);//结果有三个
}
/*为什么这两者有区别呢?
* remove是将元素的java01引用移除了,但是元素还在内存中
*而且元素java01还被obj引用,所以一个为3,一个为2
*但最终集合中的元素变了*/
sop(a1);//结果有两个
}
publicstaticvoid listIterator(){
//演示列表迭代器
ArrayList a1 =newArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java03");
sop(a1);
//只有list元素才具备这个功能,因为list元素有角标
ListIterator li = a1.listIterator();
while(li.hasNext()){
Object obj= li.next();
if(obj.equals("java02"))
//li.add("java009");正常添加
li.set("java007");//又可以修改
}
sop(a1);
while(li.hasPrevious()){
sop("pre:"+li.previous());
}
}
publicstaticvoid main(String args[]) {
//List特有方法演示
//method()
//iterator
iterator();
listIterator();
}
publicstaticvoid sop(Object obj){
System.out.println(obj);
}
}
42、 Vector
ArrayList与Vector是一样的:
区别:
1、ArrayList不是线程同步的,运行效率高;而Vector是线程同步的,运行效率低下。
2、ArrayList(可变长度数组)默认容量为 10,当超过长度为10的元素后,在往里面添加的话,它就会new一个新的数组,长度为50%延长,变成15,将原来数组中的元素copy到新数组中来,再将新元素添加到后面去
3、Vector长度也为10,当长度超过10的时候,它是100%延长,变成20.相比较而言,还是ArrayList好一些(理由:即能延长,又能节省空间,而vector比较浪费空间)
注意:在使用Vector的迭代器时,最好选用Enumeration,原因是:
由 Vector的 iterator和 listIterator方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的 remove或 add方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。Vector的 elements方法返回的 Enumeration不是快速失败的。
最重要的几个集合:
ArrayList LinkedList HashSet HashMap
Vector独特方法的演示:
package day29;
/*
*枚举就是Vector特有的取出方式。
*发现枚举和迭代器很像
*其实枚举和迭代器是一样的
*因为枚举的名称以及方法的名称都过长。
*所以被迭代器取代了。枚举郁郁而终了
* */
import java.util.Vector;
import java.util.Enumeration;
publicclass VectorDemo {
publicstaticvoid main(String args[]) {
Vector v =new Vector();
v.add("java01");
v.add("java01");
v.add("java01");
Enumeration en = v.elements();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
}
}
43、 LinkedList
LinkedList:特有方法
addFirst( );
addLast( );
getFirst( );
getLast( );
获取元素,但不删除元素,如果集合中没有元素,会出现NoSuchElementException
removeFirst( );
removeLast( );
获取元素,但是元素被删除,如果集合中没有元素,会出现NoSuchElementException
在JDK1.6时出现了替换
offerFirst( )
offerLast( )
peekFirst( )
peekLast( )
获取元素,但不删除元素,如果集合中没有元素,会返回null
pollFirst( )
pollLast( )
获取元素,但是元素被删除。如果集合中没有元素,会返回null
示例代码:
package day29;
import java.util.LinkedList;
publicclass LinkedListDemo {
publicstaticvoid sop(Object obj){
System.out.println(obj);
}
publicstaticvoid main(Stringargs[]) {
LinkedList link =newLinkedList();
link.addLast("java01");
link.addLast("java02");
link.addLast("java03");
link.addLast("java04");
// sop(link.getFirst());
// sop(link.getLast());
// sop(link.removeFirst());
// sop(link.size());
while(!link.isEmpty()){
sop(link.removeFirst());
}
}
}
44、 使用LinkedList模拟一个堆栈或者队列数据结构
堆栈:先进后出,如同被子。
队列:先进先出First in First out FIFO如同一个水管
这种封装数据的作用:在开发的过程中,总有一些人为了使方法更容易理解,而选择封装这些数据,进而自定义与这个数据相关的操作,以便使开发更简单。
示例代码:
package day29;
import java.util.LinkedList;
class DuiLie{
privateLinkedListlink;
public DuiLie(){
link =newLinkedList();
}
publicvoid myAdd(Object obj){
link.addFirst(obj);
}
publicObject myGet(){
returnlink.removeLast();//队列
//return link.removeFirst();//堆栈
}
publicboolean isNull(){
returnlink.isEmpty();
}
}
publicclass LinkedListTest {
publicstaticvoid main(String args[]) {
DuiLie d1 =new DuiLie();
d1.myAdd("java01");
d1.myAdd("java02");
d1.myAdd("java03");
while(!d1.isNull()){
System.out.println(d1.myGet());
}
}
}
45、 去除ArrayList中重复的元素
package day29;
/**
*去除ArrayList中重复的元素*/
import java.util.ArrayList;
import java.util.Iterator;
publicclass ArrayListTest {
publicstaticvoid main(String args[]) {
ArrayList a1 =newArrayList();
a1.add("java01");
a1.add("java01");
a1.add("java02");
a1.add("java01");
a1.add("java02");
a1.add("java01");
a1.add("java03");
System.out.println(a1);
a1=singleElement(a1);
System.out.println(a1);
}
publicstaticArrayList singleElement(ArrayList a1){
//定义一个临时容器
ArrayList array =newArrayList();
Iterator it = a1.iterator();
/*在迭代时循环中next调用一次,就要hasNext判断一次*/
while(it.hasNext()){
Object obj = it.next();
if(!array.contains(obj)){
array.add(obj);
}
}
return array;
}
}
由于以上LinkedList和ArrayList都有相似的功能,在开发中应该使用哪个呢?
如果开发程序中对增加、删除操作的比较频繁的话,优先使用LinkedList;对之操作的不是很频繁的话,就应该选择ArrayList(只要元素不是特别多,ArrayList中增加、删除也是允许的)。当然,如果查询比较频繁的话,肯定是ArrayList比较划算。-------android培训、java培训、期待与您交流! ----------
- 黑马程序员----集合类(一)
- 黑马程序员 集合(一)
- 黑马程序员---集合(一)
- 黑马程序员--集合(一)
- 黑马程序员---集合一
- 黑马程序员-集合(一)
- 黑马程序员——集合类(一)
- 黑马程序员--集合框架笔记(一)
- 黑马程序员--集合总结(一)
- 黑马程序员_Java集合总结(一)
- 黑马程序员_集合框架(一)
- 黑马程序员 集合框架(一)
- 黑马程序员——集合(一)
- 黑马程序员--集合框架(一)
- 黑马程序员:java集合框架(一)
- 黑马程序员------集合框架(一)
- 黑马程序员_JAVA_集合框架(一)
- 黑马程序员——集合(一)
- 十进制和26进制转换算法
- bootloader中关于Image$RW$Limit的讨论
- This application is currently offline. To enable the application, remove the app_offline.htm file fr
- linux驱动开发书籍(待续)
- django south使用
- 黑马程序员----集合类(一)
- Win32串口编程
- Boundle类的用法
- C++需要释放资源的操作
- 学遥感必读的十本书
- Oracle体系结构总结
- SQL 语句创建作业
- 使用线程池和CountDownLatch计数器来进行抓取的简单事例2
- 宏中"#"和"##"的用法