黑马程序员_Java第14天知识总结_集合类(集合框架)_Collection_迭代器_List_Set_HashSet

时间:2022-10-30 17:03:35

------- android培训java培训、期待与您交流! ----------

今天学习的知识点:
集合类(集合框架)_Collection_迭代器_List_ArrayList_LinkedList_枚举_Set_HashSet_集合中是怎样判断元素唯一性_模拟堆栈
复习String StringBuilder 基本数据类型对象包装类的练习题




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


数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的。集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。


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


集合框架:
为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式都有不同。(数据是相同的,存储的方式不同)
这个存储方式称之为:数据结构(例如:ArrayList:底层的数据结构使用的是数组结构。LinedList:使用的是链表结构。HashSet:哈希表结构)


Collection定义了集合框架的共性功能。
1,添加
add(e);
addAll(collection);


2,删除
remove(e);
removeAll(collection);//删除的是相同的部分。
clear();


3,判断。
contains(e);//是否包含某个元素。
isEmpty();//是否为空


4,获取
iterator();
size();


5,获取交集。
retainAll();//保留的是相同的部分


6,集合变数组。
toArray();






1,add方法的参数类型是Object。以便于接收任意类型对象。


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




什么是迭代器呢?
其实就是集合的取出元素的方式。
如同抓娃娃游戏机中的夹子。


迭代器是取出方式,会直接访问集合中的元素。
所以将迭代器通过内部类的形式来进行描述。
通过容器的iterator()方法获取该内部类的对象。


要访问集合容器中的元素,定义成内部类访问最方便。
就把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素。


那么取出方式就被定义成了内部类。


而每一个容器的数据结构不同,所以取出的动作细节也不一眼。
但是都有共性内容,判断和取出。那么可以将这些共性抽取。


那么这些内部类都符合一个规则,该规则是Iterator。如果获取集合的取出对象呢?
通过一个对外提供的方法。iterator();




Collection
|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。




|--Set:元素是无序,元素不可以重复。、




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



add(index,element);
addAll(index,Collection);



remove(index);



set(index,element);

get(index):
subList(from,to);//返回的是List集合的泛型。
listIterator();//返回的是列表迭代器
int indexOf(obj):获取指定元素的位置。
ListIterator listIterator();










List集合特有的迭代器。ListIterator是Iterator的子接口。


在迭代时,不可以通过集合对象的方法操作集合中的元素。
因为会发生ConcurrentModificationException异常。(并发修改异常)


所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,
只能对元素进行判断,取出,删除的操作,
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。


该接口只能通过List集合的listIterator方法获取。




枚举:


枚举就是Vector特有的取出方式。
发现枚举和迭代器很像。
其实枚举和迭代是一样的。


因为枚举的名称以及方法的名称都过长。
所以被迭代器取代了。
枚举郁郁而终了。






LinkedList:特有方法:
addFirst();
addLast();


getFirst();
getLast();
获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException


removeFirst();
removeLast();
获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException




在JDK1.6出现了替代方法。


offerFirst();
offerLast();




peekFirst();
peekLast();
获取元素,但不删除元素。如果集合中没有元素,会返回null。


pollFirst();
pollLast();
获取元素,但是元素被删除。如果集合中没有元素,会返回null。




使用LinkedList模拟一个堆栈或者队列数据结构。


堆栈:先进后出  如同一个杯子。
队列:先进先出 First in First out  FIFO 如同一个水管。


思考:
1,使用LinkedList模拟一个堆栈或者队列数据结构是基于LinkedList的,所以内部封装了LinkedList,调用了LinkedList的方法并进行封装。
2,创建一个类,创建一个LinkedList的变量,该变量在类初始化的时候new一个新的LinkedList对象。
3,调用LinkedList对象中的方法,并进行封装,例如:添加,获取,是否为空。
4,获取方法使用LinkedList的特有方法,获取元素并删除,这样可以定义条件,如果集合中的元素不为空,一直获取。
5,堆栈和队列的获取方式取决于从头角标开始获取删除元素还是从尾角标获取删除元素。




去除ArrayList集合中的重复元素。


思考:
1,定义功能,接收一个ArrayList集合,将集合中的重复元素去除后,返回一个ArrayList集合,该集合中不包含重复的元素。
2,功能中定义一个新的集合容器,用来存储原集合中不重复的元素。
3,遍历接收进来的ArrayList集合,遍历的过程中进行判断,如果新容器中不包含该元素,将元素添加到新集合容器中
4,返回新定义的集合。


总结:List集合判断元素是否相同,依据是元素的equals方法。




将自定义对象作为元素存到ArrayList集合中,并去除重复元素。


比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。




思路:
1,对人描述,将数据封装进人对象。
2,定义容器,将人存入。
3,取出。(只是取出,并没有判断是否相同并存入到新集合。毕老为了说明List集合判断元素是否相同的依据)






List集合判断元素是否相同,依据是元素的equals方法。


remove方法底层也是依赖于元素的equals方法。






|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、
|--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。


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




|--TreeSet:


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






往hashSet集合中存入自定对象
姓名和年龄相同为同一个人,重复元素。


思考:
1,判断HashSet集合中的元素是否重复依据的是元素的两个方法,hashCode和equals来完成的。
2,依据人对象中的姓名和年龄进行判断,需要复写hashCode和equals方法。
3,hashCode值根据名字的hashCode加上年龄乘以19来返回hashCode值。
4,如果hashCode值一样,判断元素,姓名和年龄是否相同,复写equals方法,里面判断的是元素的姓名以及年龄跟接收进来的元素的姓名和年龄是否相同。
总结:为了理解HashSet集合中是如何保证元素唯一性的。






通常定义一个类,因为不知道要把这个类对象存储到哪种集合框架中去,所以如果不想该类重复,通常需要复写hashCode和equals方法。






复写了昨天学习的String类、StringBuilder类、基本数据类型对象包装类的练习:






对字符串排序。
"zxcvbasdfg"


思路:
1,字符串变数组。
2,数组排序。
3,数组变字符串。


步骤:
1,定义功能,接收一个字符串,返回一个排序好的字符串。将此功能对外暴露出去,别人也可以使用。
2,封装一个将字符串变数组的功能,使用功能将字符串变成数组。  toCharArray();
3,封装一个对数组进行排序的功能(排序有选择排序、冒泡排序),使用排序功能对数组进行排序。  for for嵌套循环
4,封装一个将数组变成字符串的功能,使用功能将排序好的数组变成字符串。  String.valueOf();
5,调用封装好的功能后返回字符串。 return 






"12 0 99 -7 30 4 100 13"
要求对字符串中的数值进行排序。生成一个数值从小到大新字符串。


"-7 0 4 12 13 30 99 100"


思路:
1,将字符串切割。变成字符串数组。
2,将字符串数组转成int数组。
3,int数组排序。
4,将int数组变成字符串。


步骤:
1,定义公共函数,接收一个字符串,返回一个字符串。
2,封装功能,将字符串切割,变成字符串数组,调用功能。  split();
3,封装功能,将字符串数组转成int数组。调用功能。  定义int数组,使用for循环将字符串数组存入int数组。 Integer.pasrseInt();
4,封装功能,将int数组排序,调用功能。  Arrys.sort();
5,封装功能,将int数组变成字符串,调用功能。  定义字符缓冲区,遍历int数组,遍历过程中将遍历到的int数据存入字符缓冲区中。判断条件不为最后角标加空格。
6,调用功能结束后,返回字符串。