JAVA-7 集合框架

我们为什么需要集合框架?

对单个数据元素进行操作很简单,但是不能满足各种应用场景。比如全班一共30个学生,算班级的平均年龄。
使用数组,倒是可以实现这个目标,它可以把这30个学生的信息都存到一块连续的存储空间中,便利一遍把年龄值都加起来,再除以总数。
如果需要取出某个学生的信息,也很方便,因为每个学生有索引。数组下标对应好了就行。
但是如果要删除一个学生或者增加一个呢?
删除的情况,除了删最后一个学生的那种情况,其余的情况下,被删除学生之后的所有学生都要向前挪一位。
增加的情况,也会遇到相同的问题,因为要让位出来给新学生,还有一个问题就是,如果数组已经满了,怎么处理?
另外,如果我要把这个班的班主任的信息也放到学生们一起呢?数组是完全做不到的,因为它只能存储相同类型的元素。
通过以上分析,可以得出数组的几个缺点:

  1. 增加/删除元素不便
  2. 长度固定,扩展性差
  3. 只能放置同类型元素

集合框架有哪些?他们之间是什么关系?

这里写图片描述

集合是包含一组相关数据元素的对象,它提供了对其所包含的各种元素的操作。
所谓框架就是一个类库的集合。集合框架就是一个用来表示和操作集合的统一的架构,包含了实现集合的接口与类。

Collection:集合层次中的根接口
Set:不能包含重复的元素。SortedSet是一个按照升序排列元素的Set
List:是一个有序的集合,可以包含重复的元素。提供了按索引访问的方式
Map:包含了key-value对。Map不能包含重复的key。SortedMap是一个按照升序排列key的Map.

这里写图片描述

都继承自List的 ArrayList 和 LinkedList 有什么不一样?

学数据结构的时候,接触过两种很常见的数据结构:数组和链表,也用C语言写过,在Java中 ArrayList实现原理和数组一样,LinkedList实现原理和链表一样。
来扒一下 增加一个元素add(E e)的源码。
这是链表插入:

    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)//当前链表为空的情况
            first = newNode;
        else//链表不为空
            l.next = newNode;
        size++;
        modCount++;
    }
//双向循环链表中的一个节点 ,用Node类包起来便于操作
  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;
        }
    }

那么数组插入是怎样的呢?

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
    //去检查一下空间够不够,如果不够就要扩充容量
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

根据应用场景的特点来选择Array和Lis;

Set 和 List 有什么区别?

set不能存放相同的元素,这是它最大的一个特征。
这里写图片描述
但是需要注意的是,一般情况下,set只能识别基本数据类型是否重复,对于自定义的类型(如图的Student),需要在定义这个类时加上hashcode()方法,此方法的代码可自动生成(右键->source->hashcode() equals()).

以下是add的核心代码,目前水平还没发一下看懂~
为什么set的add 要 map的put来帮忙?

另外,由于set是无需的,遍历时只能用foreach,不能用for.

/**
     * Implements Map.put and related methods
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

HashMap 几乎是 Map系的一枝独秀,用键值对的方法来快速定位到一个对象

这里写图片描述

这里的put方法居然跟set里加一个元素的核心方法一样。why???

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值