java笔记_集合

集合视为一种容器,用于存储且只能存储引用数据类型,并提供不同的方法可以对集合进行遍历、添加、删除和查找等功能。相较于数组,集合的长度可变、可以存储不同类型的元素。

集合的继承体系图

Collection和Iterator接口

Collection接口是集合的顶层接口,它的子体系有重复的、唯一的,有有序的、无序的

Collection接口成员方法

添加功能

boolean add(Object obj)   添加一个元素
boolean addAll(Collection c)  添加一个集合的元素

删除功能

void clear()   移除所有元素
boolean remove(Object o) 移除一个元素
boolean removeAll(Collection c)  移除一个集合的元素

判断功能

boolean contains(Object o)  判断集合中是否包含指定元素
boolean containsAll(Collection c)  判断集合中是否包含指定的集合元素(包含所有元素),且返回值是表示做交集的集合是否发生过改变。 
boolean isEmpty()   判断集合是否为空

获取功能

Iterator<E> iterator()

方法:

Object next() 获取元素,并移动到下一个位置
Boolean hasNext()  如果元素仍然可以迭代,则返回true 

长度功能

int size()  元素的个数

交集功能

boolean retainAll(Collection c)  两个集合都有的元素

把集合转换为数组

Object[] toArray()

Iterator接口

概述

对collection进行迭代的迭代器
依赖于集合而存在

成员方法

boolean hasNext() :如果仍有元素可以迭代,则但会true
E next():获取元素,并移动到下一个位置

源码解析

public interface Inteator {
    boolean hasNext();
    Object next(); 
}

public interface Iterable {
    Iterator iterator();
}

public interface Collection extends Iterable { // Collection实现Iterable接口
    ...
}

public interface List extends Collection {  // List实现Collection接口
    ...
}

public class ArrayList implements List {   // ArrayList实现List接口
    public Iterator iterator() {
        return new Itr();
    }

    private class Itr implements Iterator {
        public boolean hasNext() {}
        public Object next(){} 
    }
}

Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator it = c.iterator();     //new Itr();
while(it.hasNext()) {
    String s = (String)it.next();
    System.out.println(s);
}

集合的使用步骤

a、创建集合对象

如:Collection c = new Collection();

b、创建元素对象

Student s1 = new Student("小明",18);
Student s2 = new Student();
s2.setName("小黑");
s2.setAge(26);

c、把元素添加到集合

c.add(s1);
c.add(s2);
c.add(new Student("小红",19);); // 匿名对象

d、遍历集合 (无泛型时,注意向上和向下转型的问题)

1)通过集合对象获取迭代器对象

2)通过迭代器对象的hasNext()方法判断是否有元素

3)通过迭代器对象的next()方法获取元素并移动到下一个位置

Iterator it = c.iterator();
while(it.hasNext()){
    Student s = (Student) it.next();
    System.out.println(s.getName() + "-----" + s.getAge());
}

List集合

有序的collection。此接口可以对列表中每个元素的插入位置进行精确的控制。用户可以根据元素的整数索引访问元素,并搜索列表中的元素。

特点

有序(存储和取出的元素一致)、可重复

特有功能

添加功能

void add(int index,Object element) 在指定位置添加元素

获取功能

Object get(int index)  获取指定位置的元素

列表迭代器

ListIterator listIterator()  List集合特有的迭代器

删除功能

Object remove(int index)  根据索引删除元素,返回被删除的元素

修改功能

Object set(int index, Object element)  根据索引修改元素,返回被修饰的元素

List集合的特有遍历方法

size()和get()方法结合使用

for (int x = 0; x < list.size(); x++) {
    String s = (String) list.get(x);
    System.out.println(s);
}

ListIterator的特有功能

1)继承了Iterator迭代器,所以可以直接使用hasNext()和next()方法

2)特有功能

Object previous()  获取上一个元素
Boolean hasPrevious()  判断是否有元素

注意:ListIterator可以实现逆向遍历,但是必须先正向遍历,才能逆向遍历,所以无意义,不建议使用

并发修改异常的产生原因及解决方案

ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

// 创建List集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");

// 迭代器遍历
Iterator it = list.iterator();
while (it.hasNext()) {
String s = (String) it.next();
    if ("world".equals(s)) {
        list.add("javaee");  // ConcurrentModificationException
    }
}

迭代器是依赖于集合而存在的,在判断成功后,集合中新添加了元素,而迭代器不知,所以报错,这个错误就叫并发修改异常。即:迭代器遍历元素的时候,通过集合是不能修改元素的。

解决办法

方式一:迭代器迭代元素,迭代器修改元素

// 而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
    String s = (String) lit.next();
    if ("world".equals(s)) {
         lit.add("javaee");
    }
}

方式二:集合遍历元素,集合修改元素(普通for)

for (int x = 0; x < list.size(); x++) {
    String s = (String) list.get(x);
    if ("world".equals(s)) {
        list.add("javaee");
    }
}

List的三个子类特点

a、ArrayList

底层数据结构是数组,查询快,增删慢
线程不安全,效率高

b、Vector(已有替代,现不用)

底层数据结构是数组,查询快,增删慢
线程安全,效率低

c、LinkedList

底层数据结构是链表,查询慢,增删快
线程不安全,效率高

ArrayList特有功能

Vector特有功能

a、添加功能

public void addElement(Object obj)   ---   add() 替代

b、获取功能

public Object elementAt(int index)  -- get()
public Enumeration elements()   -- Iterator iterator()
boolean hasMoreElements()  -- hasNext()
Object nextElement()  --next()

LinkedList的特有功能

a、添加功能

public void addFirst(Object e)
public void addLast(Object e)

b、获取功能

public Object getFirst()
public Object getLast()

c、删除功能

public Object removeFirst()
public Object removeLast() 

Set集合

不包含重复元素的Collection

HashSet类

Set接口的典型实现,按照Hash算法来存储集合中的元素,有很好的存取和查找性能。

1)特点

a、不保证元素的排列顺序,顺序可变

b、HashSet不是同步的,当多线程同时访问一个HashSet,则必须通过代码保证同步

c、集合元素可以是null

2)唯一性(哈希表)

添加功能依赖两个方法:

int hashCode()
boolean equals(Object obj)

LinkedHashSet类

根据元素的HashCode值来决定元素的存储位置
使用链表维护元素的次序,使元素看起来是以插入的顺序保存

public class LinkedHashSetDemo {
    public static void main(String[] args) {
        // 创建集合对象
        LinkedHashSet<String> hs = new LinkedHashSet<String>();

        // 创建并添加元素
        hs.add("hello");
        hs.add("world");
        hs.add("java");
        hs.add("world");
        hs.add("java");

        // 遍历
        for (String s : hs) {
            System.out.println(s);   // hello world java
        }
    }
}

TreeSet类

TreeSet确保集合元素处于排序状态

1)特点

排序和唯一

2)TreeSet保证元素排序和唯一性原理

唯一性:根据比较的返回是否是0来决定

排序:

A:自然排序(元素具备比较性):让元素所属的类实现自然排序接口 Comparable

B:比较器排序(集合具备比较性):让集合的构造方法接收一个比较器接口的子类对象 Comparator

public class MyComparator implements Comparator<Student> {

    @Override
    public int compare(Student s1, Student s2) {
        // int num = this.name.length() - s.name.length();
        // this -- s1
        // s -- s2
        // 姓名长度
        int num = s1.getName().length() - s2.getName().length();
        // 姓名内容
        int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
        // 年龄
        int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
        return num3;
    }
}

3)额外方法

Comparator comparator():TreeSet采用定制排序,则返回该排序所使用的Comparator;TreeSet采用自然排序,则返回null
Object first():返回集合中的第一个元素
Object last():返回集合中的最后一个元素
Object lower(Obejct e):返回集合中位于指定元素之前的元素
Object higher(Object e):返回集合中位于指定元素之后的元素
SortedSet subSet(Object fromElement,Object toElement):返回此Set的子集合,范围从fromElement到头Element
SortedSet headSet(Obecjt toEelement):返回此Set的子集,小于toElement的元素组成
SortedSet tailSet(Obejct fromElement):返回此Set的子集,有大于或等于fromElement的元素组成

4)两种排序方法

a、自然排序

TreeSet调用集合元素compareTo(Object obj)方法来比较元素之间的大小关系,再按升序排列。

:大部分类在实现compareTo(Object obj)方法时,需要将比较对象obj强制类型转换成相同类型。也就是说,向TreeSet中添加的应该是同一个类的对象,否则会引发ClassCastException异常

b、定制排序

让集合的构造方法接收一个比较器接口的子类对象 Comparator

Map集合

1)Map接口下的集合与Collection接口下的集合的存储数据的形式是不同的。

2)Collection中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储。

3)Map中的集合,元素是成对存在的。每个元素由键与值两个部分组成,通过键可以找到对应的值。

4)Collection中的集合称为单列集合,Map中的集合称为双列集合。

5)注意:Map中的集合不能包含重复的键,值可以重复,每个键只能对应一个值。

6)Map中常用的集合为 HashMap集合、LinkedHashMap集合

Map集合功能

1)添加功能

V put(K key, V value):添加元素。

如果键是第一次存储,就直接存储元素,返回null

如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

2)删除功能

void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回

3)判断功能

boolean containKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空

4)获取功能

Set<Map.Entry<K,V>> entrySet():返回键值对对象的集合
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值得集合

5)长度功能

int size():返回集合中的键值对的对数

Map三个子类

1)HashMap

键是哈希表结构,可以保证键的唯一性

HashMap<String, String> hm = new HashMap<String, String>();

hm.put("it001", "小红");
hm.put("it003", "小明");
hm.put("it004", "小张");
hm.put("it005", "小黑");

Set<String> set = hm.keySet();
for(String key : set) {
    String value = hm.get(key);
    System.out.println(key + "---" + value);
}

2)LinkedHashMap

是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序

由哈希表保证键的唯一性

由链表保证键盘的有序(存储和取出的顺序一致)

3)TreeMap

是基于红黑树的Map接口的实现,保证键的排序和唯一性

参考资料

1、《java疯狂讲义》

2、某宝购买的培训视频

3、《java从入门到精通》

-------------本文结束感谢您的阅读-------------
Mr.wj wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!