Java-容器

205 阅读4分钟

一、基本类型

容器类就是保存对象,划分为两个不同概念:

1)Collection:一个独立元素的序列,List必须按照插入的顺序保存元素,Set不能有重复元素,Queue按照排队规则确定对象产生顺序

2)Map:键值对,允许通过键来查找值.ArrayList允许使用数字来查找值

Collections是[java.util]下的类,它包含有各种有关集合操作的静态方法。

Collection是个[java.util]下的接口,它是各种集合结构的父接口。

分类概述:
List :ArrayList LinkedList
Set : HashSet(最快获取元素的方法) TreeSet(升序保存结果) LinkedHashSet(按照被添加顺序保存)
Map : HashMap(最快的查询) TreeMap(升序保存键) LinkedHashMap(按照插入顺序保存 保留查询速度)

二、List

2.1 List继承Collection接口

a.有序

b.有索引

c.允许存储重复元素

2.2ArrayList 数组结构 非同步

随机访问效率高,但插入和删除性能较低

class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, Serializable

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("a");
    System.out.println(list);  
    结果:[a, b, c, a] --add()默认在0位置插入元素
    
    list.add(3,"wutong");
    System.out.println(list); 
    结果:[a, b, c, wutong, a]

    String removeStr = list.remove(3);
    System.out.println(removeStr); //
    结果:wutong   --remove返回删除的元素
    
    String setStr = list.set(0, "A");
    System.out.println(setStr);
    结果:a  set()返回之前指定位置的元素
    
    System.out.println(list);
    结果:[A, b, c, a]

    //遍历list的三种方式:
    for (int i = 0; i < list.size(); i++) {
        String s = list.get(i);
        System.out.println(s);
    }
                                                   
    for (String s : list) {
        System.out.println(s);
    }

    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

list在for循环遍历中删除元素会发生java.util.ConcurrentModificationException

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("g");
for (String s : list) {
    if (s.equals("b")){
        list.remove(s);
    }

}
--会发生如下异常:   
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	at com.wu.tong.container.demo01.DemoList.test02(DemoList.java:72)

需要用迭代器方式遍历才可以:

public void test02(){
    List<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("g");

    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()){
        String next = iterator.next();
        if (next.equals("b")){
            iterator.remove();
        }
    }
    System.out.println(list);
}
    
结果:[a, c, g]

2.3LinkedList 链表结构 非同步

查询慢,增删快

public class LinkedList extends AbstractSequentialList implements List, Deque, Cloneable, Serializable {

LinkedList还添加了可以使用其用作栈,队列,双端队列的方法:

getFirst() element()返回列表的第一个元素而不移除,如果List为空,则抛出NoSuchElementException,peek()在列表为空时返回null

removeFirst() remove()移除并返回列表的头,如果列表为空,则抛出NoSuchElementException,poll()在列表为空时返回null

addFirst() add() addLast()都将某个元素插入到列表的尾端

removeLast()移除并返回列表的最后一个元素

LinkedList<String> linked = new LinkedList<>();
linked.add("a");
linked.add("b");
System.out.println(linked);

linked.push("tong"); 
System.out.println(linked);
结果:
[a, b, c]
[tong, a, b, c]

add()方法是从队尾插入,相当于addLast(); push()方式是从队头插入,相当于addFirst()

2.4迭代器

Iterator

(1)使用方法iterator()要求容器放回一个Iterator,Iterator将准备好返回序列的第一个元素

(2)使用next()获得序列中的下一个元素

(3)使用hasnext()检查序列中是否还有元素

(4)使用remove()将迭代器新近返回的元素删除

ListIterator是一个更大强大的Iterator的子类型,只能用于各种List的访问。双向移动

hasNext()  hasPreviouse()

2.5Stack LIFO 后进先出

Stack使用LinkedList实现的

push() 接受对象, peek() pop()将返回对象 ,peek返回栈顶元素 pop移除并返回栈顶元素

2.6Queue FIFO

offer() 将一个元素插入队尾,

peek() element() 都将在不移除的情况下返回对头,但是peek在队列为空时返回null,而element会抛出NosuchElementException异常。

poll() remove()移除并返回对头,但是poll在队列为空时返回null,而remove会抛出NosuchElementException异常。

2.7PriorityQueue 优先级队列(内部用堆(见六小节)实现)

PriorityQueue调用offer方法来插入对象时,这个对象会在队列中被排序

三、Set

继承Collection接口

1.不允许包含重复元素[重写hashcode和equals方法]

2.没有索引

2.1HashSet 内部实现是HashMap

哈希表结构(查询快),无序,非同步

哈希值:对象的逻辑地址

哈希值不相等 对象肯定不相等;哈希值相等 对象不一定相等

jdk1.8之前 哈希表= 数组+链表

之后 哈希表=数组+链表[长度<=8]

哈希表=数组+红黑树[长度>8]

HashSet 为快速查找而设计的set,存入hashSet的元素必须定义hashcode

treeSet 保持次序的Set,底层为树结构,元素必须实现Comparable

LinkedHashSet  具有hashSet的查询速度

查找是set最重要的操作,HashSet对快速查找进行有优化

HastSet输出顺序无规律可言,这是因为出于速度原因的考虑,HashSet使用了散列。

TreeSet将元素存储在红-黑树数据结构中,而HashSet使用的是散列函数

TreeSet的构造器传入String.CASE_INSENTIVE_ORDER按照字母排序

散列与散列码:

存储一组䛾最快的数据结构就是数组,所以用它来表示键的信息。但是因为数组不能调整容量,

数组并不保存键本身,而是通过键对象生成一个数字,将其作为数组的下标,这数字就是散列码

2.2LinkedHastSet

有序set

多一条链表维护存储顺序

四、Collections

Collections.addAll(list,"f","g","h","i","j");

Collections.shuffle(list);

Collections.sort(list, new Comparator() {}

Comparable 自己和参数比较 compareTo方法

Comparator 找第三方比较两个参数 compare方法

五、Map

HashMap:Map基于散列表的实现。插入和查询键值对的开销是固定的

LinkedHashMap:类似于HashMap,但是迭代遍历时,取得键值对的顺序是插入顺序

TreeMap:基于红黑树的实现,查看键或者键值对时,会被排序(次序由Comparable或Comparator决定)

map的遍历方式:
private static void show() {
    Map<String, Integer> map = new HashMap<>();
    map.put("鼠", 1);
    map.put("牛", 2);
    map.put("虎", 3);
    System.out.println(map);


    System.out.println("--------01----------");
    Set<String> str = map.keySet();
    for (String s : str) {
        System.out.println(s + " = " + map.get(s));
    }
    System.out.println("--------02---------");
    Iterator<String> iterator = str.iterator();
    while (iterator.hasNext()) {
        String key = iterator.next();
        Integer integer = map.get(key);
        System.out.println(key + "= " + integer);

    }
    System.out.println("--------03---------");
    Set<Map.Entry<String, Integer>> entries = map.entrySet();
    for (Map.Entry<String, Integer> me : entries) {
        System.out.println(me.getKey() + " = " + me.getValue());
    }
}

六、堆

完全二叉树【不要求最后一层是满的,但如果不满,则要求所有节点必须集中在最左边,从左到右是连续的,中间不能有空的】

满二叉树【除了最后一层外,每个节点都有两个孩子,而最后一层都是叶子节点,都没孩子】

满二叉树一定是完全二叉树

完全二叉树:给定任意节点,可以根据宾浩直接快速计算出其父节点和孩子节点的编号。

存储数组,节省空间,访问效率高【对比TeeeMap】

排序二叉树完全有序,每个节点有确定的前驱和后继,不能有重复元素。

堆可以有重复元素,元素间不是完全有序,但对于父子节点之间,有一定的顺序要求。根据顺序可以分为最大堆和最小堆:

1)最大堆 :每个节点都不大于其父节点

1)最小堆 :每个节点都不小于其父节点

七、用途

java容器类库的用途是"保存对象",Collection都可以用foreach语法遍历

添加元素:

可以在Collection中添加一组元素,

Arrays.asList()方法接受一个数组或是一个用逗号分隔的元素列表,并将其转化为一个List对象

Collections.addAll()方法接受一个Collection对象,以及一个数组或者用逗号分隔的列表,将元素添加到Collection中

Collection.addAll()方法只能接受另一个Collection对象作为参数,Arrays.asList和Collections.addAll()都可使用可变参数列表

List<Integer> ll = Arrays.asList(16,17,18,19);

ll.set(0, 99);

ll.add(21);//运行时错误 不支持的操作

Arrays.asList 其实底层表示的是数组,不能调整尺寸