集合总结

694 阅读8分钟

1 集合的概念

2 Collection系列

集合是Java中提供的一种容器,可以用来存储多个数据。

集合和数组既然都是容器,它们有啥区别呢?
● 数组的长度是固定的。集合的长度是可变的。
● 数组中可以存储基本数据类型值,也可以存储对象,而集合中只能存储对象。

集合主要分为两大系列: CollectionMap
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&ltT&gt接口:

实现这个接口允许对象成为"foreach"语句的目标。
换句话说,只要实现了这个接口的容器,就可以使用foreach进行遍历/迭代。
数组是编译器帮我们自动生成的类型,实现了Iterabl&ltT&gt接口。
collection系列的集合因为Collection接口继承了Iterable接口,说明Collection实现类们也实现了Iterable<T>接口。

Iterable&ltT&gt接口中有一个抽象方法:
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( )