集合框架(一)

集合框架
为什么要使用集合框架?
1.数组的长度固定
2.数组无法同时存储多个不同的数据类型
集合简单的理解就是一个长度可以改变,可以保持任意数据类型的动态数组,集合本身就是数据结果的基本概念之一,我们这里所说的集合就是java语言对这种数据结果的具体实现。
Java中的集合不是由一个类来完成的,而是由一组接口和类构成了一个框架体系,大致可以分为3层,最上层是一组接口,继而是接口的实现类
接口
Collection:集合框架最基础的接口,最顶层的接口。
List:Collection的子接口,存储有序、不唯一(元素可重复)的对象,最常用的接口
Set:Collection的子接口,存储无序,唯一(元素不可重复)的对象
Map:独立于Collection的另外一个接口,最顶层的接口,存储一组键值对象,提供键到值的映射
Iterator:输出集合元素的接口,一般适用于无序集合,从前往后输出
ListIterator:Iterator子接口,可以双向输出集合中的元素
Enumeration:传统的输出接口,已经被Iterator取代。
SortedSet:Set的子接口,可以对集合中的元素进行排序
SortedMap:Map的子接口,可以对集合中的元素进行排序
Queue:队列接口
Map.Entry:Map的内部接口,描述Map中存储一组键值对元素


Collection接口
Collection是集合框架中最基础的父接口,可以存储一组无序,不唯一的对象。
在这里插入图片描述
Collection接口可以存储一组无序,不唯一(可重复)的对象,一般不直接使用该接口,也不能被实例化,只是用来提供规范。
Collection是Iterable接口的子接口。其中包含如下常用方法
在这里插入图片描述
Collection常用子接口

  • List:存放有序、不唯一的元素
  • Set: 存放无序,唯一的元素
  • Queue:队列接口

List接口
在这里插入图片描述
List常用的拓展方法
在这里插入图片描述
List接口的实现类
ArrayList是开发中使用频率最高的List实现类,实现了长度可变的数组,在内存中分配连续的空间,所以读取快,增删慢

/**
 *   java.util.list 接口 extends Collection 接口
 *   List接口的特点:
 *       1.有序的集合,存储元素和取出元素的顺序是一致的(存储123,取出123)
 *       2.有索引,包含了一些带有索引的方法
 *       3.允许存储重复的元素
 *  *   List接口中带索引的方法(特有)
 *       - public void add(int idex,E element); 将指定的元素,添加到该集合中指定的位置上
 *       -public E get(int index); 返回集合中指定位置的元素
 *       -public E remove (int index); 移除列表中指定位置的元素,返回的是被移除的元素
 *       -public E set(int index,E element);用指定元素替换集合中指定位置的元素,返回值的更新前的元素
 *  *    注意:操作的时候一定要防止索引越界
 *  */
public class Demo01List {
    public static void main(String[] args) {

          List<String> list = new ArrayList<>() ;
             list.add("a");
             list.add("b");
             list.add("c");
             list.add("d");
        System.out.println(list);

           //在c和d之间添加一个元素
           list.add(3,"hg");

           //移除列表中指定位置的元素,返回的是被移除的元素
        String remove = list.remove(2);
        System.out.println(remove);

         //用指定元素替换集合中指定位置的元素,返回的是更新前的元素
        String d = list.set(3, "D");
        System.out.println(d);
        System.out.println(list);

           //list集合遍历有三种元素
        for (int i = 0; i <list.size() ; i++) {
              //返回集合中指定位置的元素
            String s = list.get(i);
            System.out.println(s);
        }
           //使用迭代器进行遍历
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
        }
           //使用简化版的迭代器,增强for循环
        for (String s : list) {
            System.out.println(s);
        }
    }
}

List接口的常用实现类
ArrayList:底层是基于数组的实现,非线程安全,效率高,查询快,增删慢,所有的方法都没有synchronized修饰,它的底层支持动态扩容,每次存储空间不够的时候,他都会将空间自动扩容到1.5倍大小,注意:(扩容操作涉及到内存申请和数据的搬移,是比较耗时的),所以如果事先能确定存储的数据大小最好
1.创建ArrayList时采用默认的构造函数创建集合,然后往里面添加元素,第一次添加时将数组扩容到10的大小,之后添加元素都不会在扩容,直到第11次添加然后扩容1.5倍取整,此后如果需要扩容都是1.5倍取整,但是扩容的最大值是Integer.Max.VALUE
2.每次扩容都会创建一个新的数组,然后将原数组中的数据搬移到新的数组中,ArrayList无法存储基本类型的数据,比如int 、long 需要封装成为包装类,扩容有一定的性能消耗,所以如果特别关注性能,或者希望使用基本类型,就可以选用数组
Vector:线程安全,效率低,实现线程安全直接通过synchronized修饰方法来实现的
在这里插入图片描述
Stack:Vector的子类,实现了栈的数据结构,(后进先出)

  • push:入栈方法
  • peek:取出栈顶元素,将栈顶元素复制一份,取完之后栈内的元素不变
  • pop:取出栈顶元素,直接取出栈顶元素,取完之后栈内的数据减一
    在这里插入图片描述
    linkedList:实现了先进先出的队列,非线程安全的,底层采用双向链表的形式存储,那摩什么是链表呢?链表是一种在物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,链表由一系列节点(链表中每一个元素称为一个节点)组成,节点可以在运行时动态生成,每个节点包括两个部分,一个是存储数据元素的数据域,另一个是存储下一个节点的指针域,链表与数组相反,他并不需要一块连续的内存空间,他通过指针将一组零散的内存块串联起来使用,特点:查询慢,增删快
    在这里插入图片描述

面试题ArrayList和LinkedList之间有什么区别?
1.两者在内存中存储的形式不同,ArrayList底层基于数组实现,LinkedList底层基于双重链表实现的
数组在内存中存储空间是连续的
在这里插入图片描述
链表在内存中的存储空间是非连续的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.对于随机访问,ArrayList优于LinkedList,ArrayList可以根据下标对元素进行随机访问,而LinkedList的每一个元素都依靠地址指针和他的后一个元素连接在一起,在这种情况下,查找某一个元素只能从链表头开始查询,直到查找到为止
3.对于插入和删除操作,LinkedList由于ArrayList,因为当元素被添加到LinkedList任意位置时,不需要像ArrayList那样重新计算大小或者是更新索引
4.LinkedList比ArrayList更占内存,因为LinkedList节点除了存储数据,还存储了两个指针引用,一个指向前一个元素,一个指向后一个元素
面试题:LinkedList和Stack都有pop方法,有什么区别和相同点?
pop方法都是取出集合中的第一个元素,但是两者的顺序是相反的,Stack是“后进先出”,所以pop取出的是最后一个元素,LinkedList是先进先出,所以pop取出的是第一个元素。
LinkedList实现了Deque接口,而Deque接口是Queue的子接口,Queue就是队列,底层实现了队列的数据结构
实际开发中,不能直接实例化Queue对象。
Queue的实现类是AbstractQueue,他是一个抽象类,不能直接实例化,开发中需要实现它的子类PriorityQueue.
Queue中添加的数据必须是有序的


Set
跟List一样,Set是Collection的子接口,Set集合是以散列的形式存储数据,所以元素是没有顺序的,可以存储一组无序且唯一的数据
在这里插入图片描述
Set常用实现类:

  • HashSet
  • LinkedHashSet
  • TreeSet
    HashSet是开发经常使用的一个实现类,存储一组无序且唯一的对象
    无序:元素的存储顺序和遍历顺序不一致
public class Test {
    public static void main(String[] args) {

         HashSet set = new HashSet();
             // 添加元素
            set.add("Hello");
            set.add("Spring");
            set.add("SpringBoot");
            set.add("Java");

               // 移除元素
            set.remove("Java");        
    }
}

LinkedHashSet是Set的另外一个实现类,可以存储一组有序且唯一的元素
有序:元素的存储顺序和遍历顺序一致
在这里插入图片描述

equals和==的区别?
所有类中的equals都是继承自Object类,Object类中原生的equals方法就是通过进行判断
在这里插入图片描述
但是每个类都可以对equals方法进行重写,覆盖掉之前使用
==进行判断的逻辑,改用新的逻辑进行判断是否相等。
LinkedHashSet如何判断两个对象是否相等?
首先会判断两个对象的hashCode是否相等
什么是hashCode?
将对象的内部信息(内存地址,属性值等),通过某种规则转换成一个散列值,就是该对象的hashCode.

  • 两个不同对象的hashCode值可能相等
  • hashCode不相等的两个对象一定不是同一个对象
    集合在判断两个对象是否相等的时候,会先比较他们的HashCode,如果hashcode不相等,则认为不是同一个对象,可以添加。
    如果hashcode值相等,还不能认为两个对象是相等的,需要通过equals进行进一步判断,equals相等,则两个对象相等,否则两个对象不相等
    :判断的是栈内存中的值
    引用类型的数据,栈内存中存储的是地址,所以此时
    ==判断的是引用地址
    基本数据类型,栈内存中存储的是具体的数值
    在这里插入图片描述
    TreeSet
    LinkedHashSet和TreeSet都是存储一组有序且唯一的数据,但是这里的两个有序是有区别的。
    LinkedHashSet的有序是指元素的存储顺序和遍历顺序是一致的。
    6,3,4,5,1,2----》6,3,4,5,1,2
    TreeSet的有序是指集合内部会自动对所有的元素按照升序进行排列,无论存入的顺序是什么,遍历的时候一定按照升序输出
    在这里插入图片描述
    自定义数据类型
public class TreeSetTest2 {
    public static void main(String[] args) {

        TreeSet treeSet = new TreeSet();
         treeSet.add(new Data(1));
        treeSet.add(new Data(3));
        treeSet.add(new Data(6));
        treeSet.add(new Data(3));
        treeSet.add(new Data(5));
        treeSet.add(new Data(4));
        treeSet.add(new Data(1));

        System.out.println("treeSet的长度是"+treeSet.size());
    }
}

class Data implements Comparable{
    private int num;

    public Data(int num) {
        this.num = num;
    }

    /**
     * A.compareTo(B)
     * 返回值:
     * 1 表示A大于B
     * 0 表示A等于B
     * -1 表示A小于B
     * @param o
     * @return
     */
    @Override
    public int compareTo(Object o) {
        if (o instanceof Data){
            Data data =(Data)o;
            if (this.num>data.num){
                return 1;
            }else if (this.num==data.num){
                return 0;
            }else {
                return -1;
            }
        }
           return 0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值