集合框架的概述
集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
说明
此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)
背景
1. 数组在存储多个数据方面的特点:
> 一旦初始化以后,其长度就确定了。
> 数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。
比如:String[] arr; int[] arr1; Object[] arr2;
2. 数组在存储多个数据方面的缺点:
> 一旦初始化以后,其长度就不可修改。
> 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
> 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
> 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
集合使用场景
集合的使用场景集合框架
* |----Collection接口:单列集合,用来存储一个一个的对象
* |----List接口:存储有序的、可重复的数据。 --> 又称为“动态”数组 (长度可修改)
* |----ArrayList、LinkedList、Vector
* |----Set接口:存储无序的、不可重复的数据 -->类似于高中讲的“集合”
* |----HashSet、LinkedHashSet、TreeSet
Collection接口继承树
Collection接口继承树
Collection接口中的方法的使用
实例化
(Collection是抽象方法,不能实例化,只能实例化它的子类)
Collection coll =new ArrayList();
方法
1. add(Object e):
将元素e添加到集合coll中
coll.add("AA");
coll.add(123); //自动装箱
Person p = new Person("Jerry",20);
coll.add(p);
coll.add(new Person("Jerry",20));
2. size():
获取添加的元素的个数
System.out.println(coll.size()); // 5(上面的coll长度)
3. addAll(Collection coll1):
将coll1集合中的元素添加到当前的集合中
Collection coll1 =new ArrayList();
coll1.add(456);
coll1.add("CC");
coll.addAll(coll1);
System.out.println(coll.size()); //7
4. clear():
清空集合元素
coll.clear();
5. isEmpty():
判断当前集合是否为空
System.out.println(coll.isEmpty()); // true
6. contains(Object obj):
判断当前集合中是否包含obj
我们在判断时会调用obj对象所在类的equals()。
boolean contains = coll1.contains(456); //true
System.out.println(coll1.contains(new String("CC"))); //true
coll1.add(new Person("Jerry",20)));
System.out.println(coll1.contains(new Person("Jerry",20))); //false
(要变成true则重写toString方法,要比较的对象处于第几个object,就调用多少个toString方法去对比)
7.containsAll(Collection coll1):
判断形参coll2中的所有元素是否都存在于当前集合中。
Collection coll2 = Arrays.asList(123,4567);
System.out.println(coll1.containsAll(coll2)); //false (判断coll1中是否包含123和4567,只要有一个不包含就返回false)
8. remove(Object obj):
从当前集合中移除obj元素。
Collection coll =new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
coll.remove(new String("Tom"));
System.out.println(coll); // [123, 456, Person{name='Jerry', age=20}, false]
9. removeAll(Collection coll1):
差集:从当前集合中移除coll1中所有的元素。
Collection coll1 = Arrays.asList(123,4567);
coll.removeAll(coll1);
System.out.println(coll); //[456, Person{name='Jerry', age=20}, false]
10. retainAll(Collection coll2):
交集:获取当前集合和coll2集合的交集,并返回给当前集合
Collection coll2 = Arrays.asList(123,456,789);
coll.retainAll(coll2);
System.out.println(coll); // 456
11. equals(Object obj):
要想返回true,需要当前集合和形参集合的元素都相同,与顺序无关
12. hashCode():
返回当前对象的哈希值
和数组之间相互转换
1. 集合 --->数组:
toArray()
Object[] arr = coll.toArray();
2. 数组 --->集合:
调用Arrays类的静态方法asList()
List list = Arrays.asList(new String[]{"AA", "BB", "CC"});
System.out.println(list); // [AA,BB,CC]
注意如下写法只能识别为一个元素:
List arr1 = Arrays.asList(new int[]{123, 456});
System.out.println(arr1.size());//1
应改为以下写法:
List arr2 = Arrays.asList(new Integer[]{123, 456});
System.out.println(arr2.size());//2
iterator迭代器接口:
用于遍历Collection集合元素。使用迭代器Iterator接口
内部的方法
next():
方式一:
Collection coll =new ArrayList();
coll.add(123);
coll.add(new Person("Jerry",20));
Iterator iterator = coll.iterator();
System.out.println(iterator.next()); // 123
System.out.println(iterator.next()); // Person{name='Jerry', age=20}
System.out.println(iterator.next()); // 报异常:NoSuchElementException
方式二:
for(int i = 0;i < coll.size();i++){
System.out.println(iterator.next());}
hasNext()
判断是否还有下一个元素
while(iterator.hasNext()){
System.out.println(iterator.next());} //①指针下移 ②将下移以后集合位置上的元素返回
❌ 错误写法一:
指针下移两次,检查第一个,输出第二个
Iterator iterator = coll.iterator();
while((iterator.next()) != null){
System.out.println(iterator.next());}
❌ 错误写法二
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
while (coll.iterator().hasNext()){
System.out.println(coll.iterator().next());}
remove()
内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove()
Iterator iterator = coll.iterator();
while (iterator.hasNext()){ //如果有下一个元素,则返回true
Object obj = iterator.next();
if("Tom".equals(obj)){ // 如果集合中找到Tom
iterator.remove();}} // 则移除
iterator = coll.iterator(); // 遍历集合,必须重新得到一个全新的迭代器对象(指针移到初始位置)
while (iterator.hasNext()){
System.out.println(iterator.next());}}
⚠️ 如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。
⚠️ 集合对象每次调用iterator()方法都得到一个全新的迭代器对象
⚠️ 默认游标都在集合的第一个元素之前。
Foreach
jdk 5.0 新增了foreach循环,用于遍历集合、数组,内部仍然调用了迭代器。
格式:for(集合元素的类型 局部变量 : 集合对象)
遍历集合
for(Object obj : coll){
System.out.println(obj);}
遍历数组
int[] arr =new int[]{1,2,3,4,5,6};
//for(数组元素的类型 局部变量 : 数组对象)
for(int i : arr){
System.out.println(i);}
⚠️ 使用增强for循环赋值,不会改变arr的值,只是将arr的值赋给了i,i做了改变
for(String i : arr){
i ="AA";}
for (String i : arr){
System.out.println(i);}
Collection子接口
List接口
通常用来替代数组,List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引
List接口框架
|----Collection接口:单列集合,用来存储一个一个的对象
|----List接口:存储有序的、可重复的数据。 -->“动态”数组,替换原有的数组
|----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
|----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
|----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储
源码分析
ArrayList
jdk 7情况下
ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
list.add(123);//elementData[0] = new Integer(123);
...
list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)
jdk 8中ArrayList的变化:
ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没有创建长度为10的数组
list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
...
后续的添加和扩容操作与jdk 7 无异。
小结
jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。
LinkedList
LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象。其中,Node定义为:体现了LinkedList的双向链表的说法
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev; }}
Vector
jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。
在扩容方面,默认扩容为原来的数组长度的2倍。
方法的使用
ArrayList
void add(int index, Object ele):在index位置插入ele元素
boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
Object get(int index):获取指定index位置的元素
int indexOf(Object obj):返回obj在集合中首次出现的位置
int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index, Object ele):设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
总结:常用方法
增:add(Object obj)
删:remove(int index) / remove(Object obj)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
长度:size()
遍历: ① Iterator迭代器方式
② 增强for循环
③ 普通的循环
网友评论