1 集合的概念
2 Collection系列
集合是Java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?
● 数组的长度是固定的。集合的长度是可变的。
● 数组中可以存储基本数据类型值,也可以存储对象,而集合中只能存储对象。
集合主要分为两大系列: Collection和Map。
Collection表示一组对象 ,每组对象中的每一个对象是独立的;
Map表示一组映射关系或键值对。
1.1 java.util.Collection接口
根接口: java.util.Collection<E>
E:代表Element元素,即表示<E>代表的是集合中元素的类型。
1.2 Collection接口API(常用方法)
因为无论你是Set还是List,只要是Collection系列的集合,都有Collection接口中的方法。
1、添加元素
boolean add(E e): 添加一个元素
boolean addAll(Collection<? extends E> c) : 把c集合中的所有元素都添加到当前集合中this = this ∪ c;
2、删除元素
void clear():清空所有元素
boolean remove(Object o) :删除第一个找到的元素
boolean removeAll(Collection<?> c) :从当前集合中删除与c集合中一样的元素
this = this - this ∩ c
boolean retainAll (Collection<?> c):从当前集合中删除和c非共有的元素,即当前集合中只保留它俩的交集 this = this ∩ c;
3、查询元素
boolean isEmpty() :是否为空集合
boolean contains(object o) :是否包含某个元素
boolean containsAll (Collection<?> c) :是否包含C中的所有元素
判断c是否是当前集合的子集
int size(): 返回集合的元素的个数
4、遍历
代码:
public class TestContainer {
@Test
public void test() {
//(1)创建集合对象,相当于准备了一个容器
// 这个集合中你要装什么类型的元素,需要指定泛型。例如,我要装学生的姓名<E>指定为<String>
// Collection是接口,不能创建对象,就创建它实现类的对象
//因为Collection接口没有直接实现类,有它子接口(如Set和List)的实现
//这里先用一个实现类: ArrayList
Collection<String> c = new ArrayList<String>();
//(2)让容器中添加元素对象c.add("张三");
c.add("李四");
c.add("王五");
System.out.println(c);
}
}
1.3 Collection系列的集合遍历
1、使用数组
object[ ] toArray():转成数组,然后遍历。
2、使用foreach
foreach:增强for循环
语法结构:
for(集合的元素类型 元素名 : 容器名称) {
}
元素名:自己命名
foreach循环的原理:
它其实是使用了Iterator迭代器来遍历集合的。
java.lang.Iterable<T>接口:
实现这个接口允许对象成为"foreach"语句的目标。
换句话说,只要实现了这个接口的容器,就可以使用foreach进行遍历/迭代。
数组是编译器帮我们自动生成的类型,实现了Iterabl<T>接口。
collection系列的集合因为Collection接口继承了Iterable接口,说明Collection实现类们也实现了Iterable<T>接口。
Iterable<T>接口中有一个抽象方法:
Iterator iterator( )
3、使用迭代器
Iterator iterator( ) : 返回一个专门遍历当前Collection集合的迭代器,这个方法是从Iterable接口继承的。
可以理解为,公交车上的检票员。检票员的作用就是查看这个公交车上的每一个乘客。
迭代器的作用:就是查看集合中的每一个元素的对象。
Iterator这个类型有两个方法用于遍历集合:
①boolean hasNext(): 判断后面是否还有其他元素
②E next( ):取出元素
// 遍历1:toArray
public void test() {
Collection<Integer> c = new ArrayList<Integer>();
c.add(1);//装进去Integer对象,自动装箱
c.add(2);
Object[] array = c.toArray();
int sum=0;
for (int i = 0; i < array.length; i++) {
sum+=(Integer)array[i];//强转原因:编译时按照Object处理
}
System.out.println(sum);
}
// 遍历2:Iterator
public void test2() {
Collection<String> c = new ArrayList<String>();
c.add("张三");//装进去Integer对象,自动装箱
c.add("李四");
Iterator<String> iterator=c.iterator();
while (iterator.hasNext()){//判断后面是否还有元素遍历,2个元素hasNext()执行3遍,next()执行2遍
String next = iterator.next();
System.out.println(next);
}
}
// 遍历3:foreach
public void test3() {
Collection<String> c = new ArrayList<String>();
c.add("张三");//装进去Integer对象,自动装箱
c.add("李四");
for (String e : c) {
System.out.println(e);
}
String[] arr = {"hello","world"};
for (String string : arr) {
System.out.println(string);
}
}
1.4 删除Collection元素
(1)集合.remove(object obi):删除一个元素
适用删除指定的元素,无法根据条件删除
(2)迭代器.Remove()
在遍历集合的过程中,可以根据条件来删除元素
使用foreach遍历,然后遍历的过程中调用集合的remove(元素),发现报ConcurrentModificationException(并发修改异常), 在使用foreach遍历的同时再调用集合的add ,remove都会导致错误,即foreach遍历时,不允许修改集合的元素个数。
1、明确删除
// 集合.remove()
public void test() {
Collection<Integer> c = new ArrayList<Integer>();
c.add(1);//装进去Integer对象,自动装箱
c.add(2);
c.add(3);
c.add(4);
// 删除集合中的偶数
for (Integer num:c) {
if (num%2==0){
// 错误
c.remove(num);//java.util.ConcurrentModificationException
}
}
System.out.println(c);
}
2、根据条件删除
// 迭代器.remove()
public void test() {
Collection<Integer> c = new ArrayList<Integer>();
c.add(1);//装进去Integer对象,自动装箱
c.add(2);
c.add(3);
c.add(4);
// 删除集合中的偶数
Iterator<Integer> iterator= c.iterator();
while (iterator.hasNext()) {
Integer num = iterator.next();
if (num%2==0){
// 正确。迭代器遍历集合时,要删除元素,得迭代器自己删除,不能用集合的remove方法
iterator.remove();
}
}
System.out.println(c);
}
java.util.Iterator 和 java.lang.Iterable
java.lang.Iterable:表示可迭代的,它的抽象方法Iterator iterator( ),实现这个接口意味着可以使用foreach遍历。Java框架集合中Collection系列的集合都实现了这个接口,意味着可以使用foreach遍历。而Map系列集合没有实现接口,不能直接使用foreach,需要通过entrySet(),keySet(),values()进行转换,然后再使用foreach。
java.util.Iterator:表示迭代器。每一种实现了Iterable接口的集合内部,都会有一个内部类,例如:ArrayList内部有一个Itr内部类,实现Iterator接口,用于集合的迭代。
** java.util.Iterator的抽象方法:**
(1)boolean hasNext()
(2)E next()
(3)void remove()
java.util.lterator 的子接口: java.util.Listlterator。
List 系列的集合内部有提供 Listlterator ( )方法可以获取 Listlterator 对象。在 List 系列的集合内部有内部类实现了Listlterator 接口。它的抽象方法:
( 1 ) boolean hasNext ( )
( 2 ) E next ( )
( 3 ) void remove ( )
( 4 ) boolean hasPrevious( )
( 5 ) E previous ( )
( 6 ) void add ( E e )
( 7 ) void set (E e )
( 8 ) int nextlndex ( )
( 9 ) int previouslndex ( )
1.3 List系列
1.3.1 List系列的集合特点
(1)有序,可以通过索引/下标进行操作
(2)可重复的:调用equals相同的元素
1.3.2 List集合的API
在Collection接口的API基础之上增加如下方法:
1、添加
add(int index, E e) :在[index]位置添加一个
addAll(int index , Collection c) :在[index]位置添加多个
2、删除
E remove(int index) :删除[index]位置的元素,返回被删除的元素
3、修改
E set(int index, E e) :替换[index]位置的元素,返回被替换的元素
4、查询
E get(int index) :返回[index]位置的元素
List subList(int start, int end) :截取[start,end)部分的元素 int indexOf(Object obj) :返回obj在当前集合中第一次出现的下标
int lastIndexOf(Object obj) :返回obj在当前集合中最后一次出现的下标5、遍历
在原来lterator和foreach遍历的基础上增加了:
Listlterator listerator() :默认游标在[0]开始
Listlterator listerator(int index) :默认游标在[index]位置
1.3.3 List接口的常用实现类
1、ArrayList :动态数组
2、Vector :动态数组
3、LinkedList :双向链表
4、Stack :栈
面试题: ArrayList与Vector的区别
ArrayList:新一点,线程不安全,扩容的机制默认为原来的1.5倍
Vector :最古老的动态数组,线程安全的,扩容的机制默认为原来的2倍,还多支持了一个旧版的迭代器Enumeration迭代。
面试题:动态数组与双向链表的区别?
面试题:栈的特点:先进后出
1.4 Set系列
1.4.1 Set系列的集合的特点
(1)不可重复
(2) TreeSet :按大小顺序, LinkedHashSet :按照添加的顺序, HashSet :无序
1.4.2 Set接口的实现类们
HashSet/LinkedHashSet :
如何区别元素的不可重复?
依赖于元素的hashCode和equals方法。
TreeSet :
如何区别元素的不可重复以及如何保证元素的大小顺序?
要么元素实现java.lang.Comparable接口,重写int compareTo(T t)方法,
要么指定java.util.Comparator接口的实现类对象,重写int compare(T t1, T t2)方法
如果希望保持一致性,在重写compareTo时,一般也会重写equals方法。不是语法要求,而是逻辑意义问题。
1.5 Map系列
1.5.1 Map系列的集合的特点
1、存储键值对 (key,value) ,也称为映射关系,键值对是Map,Entry接口的实现类对象。
2、所有存储到Map中的key不能重复
3、所有存储到Map中的value可以重复
1.5.2 Map接口的API
1、添加
put(K key,V value) :两个形参,一对键值对 ,同一个key如果put两次,第二次会覆盖上一次的value
putAll(Map m) :将一个map中的所有键值对添加到当前map中
2、删除
void clear() :清空
remove(Object key) :根据key删除-整对键值对(key,value)
3、查询
int size() :键值对的数量
boolean containsKey(Object key) :是否包含某个key
boolean containsValue(Object value) :是否包含某个value
V get(Object key) :根据key获取value值
4、遍历
(1)遍历所有的键值对: Set<Entry<K,V>> entrySet( )
(2)遍历所有的key : Set<K> keySet( )
(3)遍历所有的value : Collection<V> values( )