Java 集合框架Collection,Set,List,Queue

Collection,Set,List,Queue


image_1cbo7pg32304p7i13q91qcgadp9.png-261.3kB

  Collection 是List,Set和Queue的父接口。该接口里面定义的方法既可以操作List,Set,Queue集合.由于Collection 是 List,Set,Queue的父接口,

方法 解释
boolean add(Object obj) 添加成功 true
boolean addAll(Collection v) 将集合c添加到指定的集合,true成功
void clear() 清除集合里面的所有元素,长度变为0
boolean contains(Object obj) 集合里面是否包含指定元素
boolean containsAll(Collection c) 集合里面是否包含集合集合c里面的所有元素
boolean isEmpty() 集合是否为null,当集合长度为0时返回true
Iterator iterator() 返回一个Iterator对象,用于遍历集合中的元素
boolean remove(Object obj) 删除集合中指定元素obj 当集合中包含多个obj只能删除第一个,成功返回ture
boolean removeAll(Coolection c) 从集合中删除指定中里不包含c的元素,如果该操作改变了集合(相当于取指定集合和c的交集),返回true
int size() 返回集合中元素的个数
Object[] toArray() j将发放转换为一个数组集合

Set

  Set集合它类型于一个罐子,程可以将多个对象“丢进”Set集合里面。

  1. Set集合是无序的,不能记住添加顺序,当取出元素时,是无序的
  2. Set集合不允许包含重复的元素,Set集合里面可以包含null元素,但是只能有一个null
  3. Set集合与Collection 基本相同,没有任何额外的方法

HashSet

  HashSet是Set接口的实现类,HashSet 是按Hash算法来存储集合中的元素,拥有很好的存取,和查询性能。

@Test
    public  void  test01(){
        Set<String> set = new HashSet<>();

        set.add("AAAA");
        set.add("BBBB");
        set.add("CCC");
        set.add("DDD");
        //可以看到set 输出是无序的
        System.out.println(set);

        System.out.println("移除AAAA:"+set.remove("AAAA"));

        System.out.println(set);
    }

image_1cc54adhc1pq0ois1sck19ok1irr9.png-13.8kB

什么是Hash:

LinkHashSet

  LinkHashSet 是HashSet的子类,LinkHashSet是根据hashCode值来决定元素存储的位置,但它同时同链表维护元素的位置,当元素取出元素时,和插入位置相同。

LinkHashSet 性能略微低于HashSet, 因为它用使用了链表维护元素的顺序

    @Test
    public void test01(){
        Set<String> set = new LinkedHashSet<>();

        set.add("AAA");
        set.add("BBB");
        set.add("CCC");
        set.add("DDD");

        System.out.println(set);
    }

image_1cc55to9t1d9m1opn8va1a8e1i2j16.png-4.9kB

TreeSet

   ThreeSet是SortSet 接口的实现类,ThreeSet 可以保证元素处于排序状态。当你添加元素元素后ThreeSet会默认使用自然排序法,将元素排序。ThreeSet 采用的红黑树的数据结构来存储集合元素。

方法 解释
Comparator comparator() 如果ThreeSet采用了定制排序,则方法返定制排序所用的Comparator,如果采用的是自然排序,返回的是null
Object first() 返回第一个元素
Object last() 返回最后一个元素
Object lower() 返回小于指定元素的第一个元素
Object higher() 返回大于指定元素的第一个元素
SortSet subSet(Object fromElement,Object toElement) 指定返回元素的范围,fromElement(包含),toElement(不报喊)
SortSet headSet(Object toElement) 返回小于toElement的元素集合
SortSet tailSet(Object toElement) 返回大于或等于toElement的元素集
    @Test
    public void test01(){
        TreeSet<String> set = new TreeSet<>();
        set.add("22");
        set.add("10");
        set.add("80");
        set.add("-20");
        //输出的元素的有序的
        System.out.println(set);
            //返回22之前的第一个元素
        System.out.println("小于的第一个元素:"+treeSet.lower("22"));
        System.out.println("大于的第一个元素:"+treeSet.higher("10"));
        System.out.println("第一个元素:"+treeSet.first());
        System.out.println("最后一个元素:"+treeSet.last());
        System.out.println("返回小于指定元素的集:"+treeSet.headSet("22"));
    }

image_1ccbjv6br1oll844jonjmk1r6pm.png-16.4kB

List

  List作为Collection 的子接口,当然可以使用Collection接口里面的所有方法。List集合是有序的,可以重复的,集合中每个元素都有对应的顺序索引。索引是从0开始的。

方法 解释
void add(int index,Object obj) 将obj元素插入到List集合的index处
boolean addAll(int index,Collection c) 将集合所包含的所有元素都插入到List集合index处
Object get(int index) 返回index索引的位置
int indexOf(Object 0) 返回对象0在List集合中第一次出现的位置
int lastIndexOf(Object o) 反会对象o在List最后一次出现的位置
Object remove(int index) 删除并返回index索引处的元素
Object set(int index,Objext obj) 将index索引的元素替换成obj,返回被替换的旧元素
List subList(int indexfromIndex,int toIndex) 返回索引fromIndex(包含)到toIndex(不包含)处所有集和组成的子元素([fromIndex,toIndex)区间)
@Test
    public void listTest(){
        List<String> books = new ArrayList<>();
        //向books集合中添加3个元素
        books.add("111");
        books.add("222");
        books.add("333");
        books.add("444");
        System.out.println(books);

        //向第二位置添加元素,后面的元素都向后移动
        books.add(1,"555");
        for(String str:books){
            System.out.print(str+"\t");
        }

        //移除第二个元素
        System.out.println("移除的元素为:"+books.remove(1));
        System.out.print("移除后的元素为:");
        for(String str:books){

            System.out.print(str+"\t");
        }
        System.out.println();
        System.out.println("将索引为0的位置的元素:"+books.set(0, "aaa")+"修改为:"+books.get(0));

        //获取索引为1,2的集合,subList的区间为:[1,3)
        List<String> subList = books.subList(1, 3);
        System.out.println(subList);
    }

image_1cbosdri37isiaa24keu21etn2k.png-27.7kB

下面两个方法是Java8

方法 解释
void replaceAll() 根据operator指定的计算规则重新设置Lsit集合所有元素
void sort(Comparator c) 根据Comparator参数对List集合排序

Arrays.asList

   ArrayList 是一个固定长度的List集合程序只能遍历访问该集合中的元素不可增加,删除集合中的元素。

 List<String> list = Arrays.asList("AAA","BBB","CCC");

ArrayList 和 Vectory

  ArrayList和Vectory作为List接口的实现类,底层是通过数组实现的,数组是一种效率最高的存储和随机访问对象引用序列的方式,数组就是一个简单的线性序列,但是数组有一个致命的缺点,数组对象的大小被固定,期生命周期不可变。每次ArrayList扩容时,都会将原来的数据对象拷贝到新的容器里面。因此ArrayList的效率将会比数组低很多。

jdk8 ArrayList 的grow方法


  /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //当ArrayList扩容时,是带符号右移动一位
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
  • ArrayList 每次扩容并不是原来的1.5倍

上面源码可以看到 int newCapacity = oldCapacity + (oldCapacity >> 1); oldCapacity + oldCapacity带符号向右移动一位

10 的二进制 1010 当第一次移动后二进制变为: 1010 + 0101 结果: 15,当第二次扩容时: 1111 + 0111 结果:22 ,当第三次移动:0001 1010 + 0000 1101 = 37。
所以说并不是的1.5倍。

ArratList 和Vector 的区别

  ArrayList 是线程不安全的,主要体现在多个线程对同一个ArrayList添加元素,就会出现问题。
体现文章:https://blog.csdn.net/zx6571269/article/details/79960415
  Vector 是线程安全的,性能比ArrayList低,但是在实际开不会使用Vectory,而是使用Coollection的工具类来包装将ArrayList转换为线程安全的。

Queue 接口

   Queue是Colletion的子接口 用于模拟队列这种数据集合,队列通常是指“先进先出”,新插入的元素在队列尾部,队列不允许随机访问。

方法 解释
void add(Object obj) 将指定的元素加入此队列的尾部
Object element() 获取队列又不元素,但是不删除该元素
boolean offer(Object obj) 将指定元素加入到此队列的尾部,当使用有容量限制的,队列这个方法比add好
Object peek() 获取队列头部的元素,但是不能删除该元素,如果队列为null返回null
Object poll() 获取头部的元素,并删除该元素
Object remove() 获取队列头部的元素并删除该元素

PriorityQueue

  PriorityQueue是Queue的实现类,PriorityQueue保存队列的顺序并不是按加入队列的顺序,而是根据队列元素的大小重新排序。


public static void main(String[] args) {
        PriorityQueue<String> priorityQueue = new PriorityQueue<>();

        priorityQueue.add("2");
        priorityQueue.add("5");
        priorityQueue.add("-5");
        priorityQueue.add("1");

        for (String str : priorityQueue) {
            System.out.print(str + "\t");
        }
        System.out.println();

        System.out.println("首部元素为:" + priorityQueue.peek());

    }

可以看到元素是按重小到大的顺从。

Deque接口

  Deque接口是queue的子接口,它代表一个双端队列。

方法 解释
void addFirst(Object obj) 将指定元素插入该双端队列的开头
void addLast(Objcet obj) 将该元素插入到双端队列的末尾
Iterator descendingIterator() 返回该双端队列对应的迭代器,以逆向顺序来迭代队列中的元素
Object getFirst() 获取但不能删除双端队列的第一个元素
Object getLast() 获取但不能删除双端队列的最后一个元素
Object peekFrist() 获取但不删除双端队列的第一个元素
Object peekLast() 获取但不删除双端队列的最后一个
Object pollFirst() 获取并删除双端队列的第一个元素
Object pollLast() 获取并删除双端队列的最后一个元素
Object pop() 相当于remove First
void push(Object obj) 相当于addFirst(obj)
Object removeFirst 移除双端队列的第一个元素
Object removeLast() 获取并删除该双端队列的一个元素
boolean removeFirstOccurrence(Object obj) 删除双端队列的第一次出现的元素obj
boolean removeLastOccurrence(Object obj) 删除双端队列最后一次出现的元素

ArrayDeque

ArrayDeque是Deque接口的实现类,ArrayDeque和ArrayList两个集合类的实现相似,他们的底部都是采用动态的Object数组。
  • ArrayDeque模拟statck的使用
public static void main(String[] args) {
        ArrayDeque<String> stack = new ArrayDeque<>();

        //将元素依次进行push入栈
        stack.push("aaaa");
        stack.push("bbbb");
        stack.push("cccc");
        stack.push("dddd");
        //打印栈里面的元素
        System.out.println(stack);
        //访问栈顶元素
        System.out.println("访问栈顶元素"+stack.peek());

        System.out.println();
        //stack 进行出栈操作,栈顶出栈
        System.out.println(stack.pop());
        //打印出栈后的数据
        System.out.println(stack);
        Iterator<String> iterator = stack.descendingIterator();
        //以逆向顺序来迭代队列中的元素
        while (iterator.hasNext()) {
            System.out.print(iterator.next()+"\t");

        }
    }

image_1cc2spcjoat41j1i1evae96r3l9.png-15.6kB
在需要使用到”栈”这种数据结构时,使用ArrayDeque,不要使用stack,stack比较古老了,性能较差

  • ArrayDeque 模拟队列的使用
public static void main(String[] args) {
        ArrayDeque<String> queue = new ArrayDeque<>();

        queue.offer("AAAA");
        queue.offer("BBBB");
        queue.offer("CCCC");
        queue.offer("DDDD");

        //打印队列李里面的元素
        System.out.println(queue);
        //打印队列头部的元素
        System.out.println("队列头部的元素"+queue.peek());

        System.out.println("出队操作:"+queue.poll());

        System.out.println(queue);

    }

image_1cc2u5su31jfvsci1sb7ife6le9.png-13.6kB

  LinkList实现List接口和Deque接口。

  1. LinkList 可以根据索引来访问集合中的元素,因为它实现了List接口
  2. LisnkList 还可以当做双端队列来使用,因为它实现了Deque接口,当然它可以当做”栈”或者”队列”来使用

Collection 工具类

Collections.synchronizedXXX 同步控制

  在Java中在集合框架的实现类:HashSet,ArratList,ArrayDeque,LinkList,HashMap,ThreeMap都是线程不安全的,该方法可以将指定集合包装成为线程同步的集合,可以解决多线程并发访问集合时出现的线程安全问题。

image_1ccbki55010hcvh6kiabh1da213.png-48.9kB

Collection 排序

方法 解释
void reverse(List lsit) 反转指定List集合中的元素顺序
void shuffle(List list) 对List集合进行随机排序
void sort(List list) 对List集合进行自然顺序排序(升序)
void swap(List list,int i,int j) list集合中交换i和j的位置
void rotate(List list,int distance) distance 为正数时,将list集合的后distance个元素移动到前面来,当distance为负数时,将前distance个元素移动都后面,不会改变list的长度

查找、替换

方法 解释
int binarySearch(List list,Object key) 使用二分查找,获取指定对象在List集合索引位置,返回的索引位置(该方法必须保证List集合中的元素是有序的)
int frequency(Collection c,Object obj) 返回指定集合中指定元素出现的次数

总结:

  • 当遍历集合元素时:

    • 对于List和vector采用随机访问方法来遍历(for() foreach)来遍历,这样性能更好。
    • 对于LinkList来说使用Iterator遍历性更好
  • 如果要经常执行插入,删除操作改变List集合大小,可以使用LinkList集合,因为ArrayList,Vectory集合可能需要经常分配内部数组的大小,性能比LinkList低。

  • 当有多个线程要用时访问List集合中的元素时,可以使用Collection将集合包装成线程安全的集合

猜你喜欢

转载自blog.csdn.net/zx6571269/article/details/80161265