Java集合框架(一)

1.Collection集合

1.1数组和集合的区别【理解】

  • 相同点

    都是容器,可以存储多个数据

  • 不同点

    • 数组的长度是不可变的,集合的长度是可变的

    • 数组可以存基本数据类型和引用数据类型

      集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类

1.2集合类体系结构【理解】

1.3Collection 集合概述和使用【应用】

  • Collection集合概述

    是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素

    JDK 不提供此接口的任何直接实现.它提供更具体的子接口(如Set和List)实现

    collection的特点:

    1:有序:部分集合实现是有序的,部分集合实现是无序的。这里的有序指的是存储的顺序。

    2:可排序:部分集合实现是可排序的,部分集合实现是不可排序的。

    3:可重复:部分集合是可重复的,部分集合是不可重复的。

    既然每一个集合的特点不一样,那么就取决于所有子类的实现方法不一样,但是我们知道,在集合中所有的集合应该具有集合共有特点:

    1:长度可变

    2:能够存储任意的引用类型

    3:具备很多对象的增删改查的方法

    4:集合也能够存储基本数据类的包装类

  • 创建Collection集合的对象

    • 多态的方式

    • 具体的实现类ArrayList

  • Collection集合常用方法

    方法名说明
    boolean add(E e)添加元素
    boolean remove(Object o)从集合中移除指定的元素
    boolean removeIf(Object o)根据条件进行移除
    void clear()清空集合中的元素
    boolean contains(Object o)判断集合中是否存在指定的元素
    boolean isEmpty()判断集合是否为空
    int size()集合的长度,也就是集合中元素的个数
    retainALL求交集,返回的结果是是否有交集,有交集返回true,没有交集返回false

1.4Collection集合的遍历【应用】

所有的实现了Collection接口的集合类都有一个iterator()方法,该方法返回一个Iterator接口对象。提供的有集合数据遍历的方式。

  • 迭代器介绍

    • 迭代器,集合的专用遍历方式

    • Iterator<E> iterator(): 返回此集合中元素的迭代器,通过集合对象的iterator()方法得到

  • Iterator中的常用方法

    boolean hasNext(): 判断当前位置是否有元素可以被取出 ​ E next(): 获取当前位置的元素,将迭代器对象移向下一个索引位置

  • Collection集合的遍历

    public class IteratorDemo1 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<>();
    ​
            //添加元素
            c.add("hello");
            c.add("world");
            c.add("java");
            c.add("javaee");
    ​
            //Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
            Iterator<String> it = c.iterator();
    ​
            //用while循环改进元素的判断和获取
            while (it.hasNext()) {
                String s = it.next();
                System.out.println(s);
            }
        }
    }

  • 迭代器中删除的方法

    void remove(): 删除迭代器对象当前指向的元素

    public class IteratorDemo2 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<>();
            list.add("a");
            list.add("b");
            list.add("b");
            list.add("c");
            list.add("d");
    ​
            Iterator<String> it = list.iterator();
            while(it.hasNext()){
                String s = it.next();
                if("b".equals(s)){
                    //指向谁,那么此时就删除谁.
                    it.remove();
                }
            }
            System.out.println(list);
        }
    }

1.5增强for循环【应用】

  • 介绍

    • 它是JDK5之后出现的,其内部原理是一个Iterator迭代器

    • 实现Iterable接口的类才可以使用迭代器和增强for

    • 简化数组和Collection集合的遍历

    • 所有的单列集合和数组才能用增强for进行遍历

  • 格式

    for(集合/数组中元素的数据类型 变量名 : 集合/数组名) {

    // 已经将当前遍历到的元素封装到变量中了,直接使用变量即可

    }

  • 快速生成方式:集合的名字.for

  • 代码

    public class MyCollectonDemo1 {
        public static void main(String[] args) {
            ArrayList<String> list =  new ArrayList<>();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            list.add("e");
            list.add("f");
    ​
            //1,数据类型一定是集合或者数组中元素的类型
            //2,str仅仅是一个变量名而已,在循环的过程中,依次表示集合或者数组中的每一个元素
            //3,list就是要遍历的集合或者数组
            for(String str : list){
                System.out.println(str);
            }
        }
    }

2.List集合

2.1List集合的概述和特点【记忆】

  • List集合的概述

    • 有序集合,这里的有序指的是存取顺序

    • 用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素

    • 与Set集合不同,列表通常允许重复的元素

  • List集合的特点

    • 存取有序

    • 可以存储重复元素和空值

    • 有索引

2.2List集合的特有方法【应用】

方法名描述
void add(int index,E element)在此集合中的指定位置插入指定的元素
E remove(int index)删除指定索引处的元素,返回被删除的元素
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素
int indexof(object o)返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int LastIndexof(object o)返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
List<E> subList(int fromIndex,int toIndex)返回列表中指定的fromIndex(含)和toIndex之间的元素。

2.3ListIterator接口

ListIterator接口是Iterator接口的子接口,在Iterator正向迭代的基础上扩展了逆向迭代的操作。

3.数据结构

3.1数据结构之栈和队列【记忆】

栈结构(LIFO)

先进后出

Stack特点:1:基于栈结构的集合,先进后出。2:Stack类是Vector的子类,所以该类也是线程安全的,效率低。

压栈:push

获取栈顶元素:peek

弹栈(获取栈顶的元素并弹出):pop

测试栈是否为空:empty

返回对象在栈中的位置,以1为基数:search(object o)

注:如果栈中的元素为空,那么再次尝试弹栈(pop方法),将会抛出EmptyStackException。

队列结构(FIFO)

先进先出

Queue特点:

1、该接口是队列接口的根接口,先进先出。

2、该接口提供队列相关的两种形式的方法,一种抛异常,一种返回一个特殊的值(null或false)

常用方法:

抛出异常返回特殊值
插入add(e)offer(e)
移除removepoll()
只取数据,不弹出elementpeek()

3.2Deque(双端队列)

特点:

1、Deque是一个Queue的子接口,是一个双端队列,支持在两端插入和移除元素。

2、deque支持索引值直接存取。

3、Deque头部和尾部添加或移除元素都非常快速。但是在中部安插元素或移除元素比较费时。

4、插入、删除、获取操作支持两种形式:快速失败和返回null或true\false。

5、不推荐插入null元素,null作为特定返回值表示队列为空。

常用方法:

第一个元素(头部)最后一个元素(尾部)
抛出异常特殊值抛出异常特殊值
插入addFirst(e)offerFirst(e)addLast(e)offerLast(e)
移除removeFirst()pollFirst()removeLast()pollLast()
检查getFirst()peekFirst()getLast()peekLast()

双向队列操作

插入元素:

  1. addFirst():向队头插入元素,如果元素为null,则发生空指针异常。

  2. addLast():向队尾插入元素,如果为空,则发生空指针异常。

  3. offerFirst():向队头插入元素,如果插入成功返回true,否则返回false。

  4. offerLast():向队尾插入元素,如果插入成功返回true,否则返回false。

移除元素:

  1. removeFirst():返回并移除队头元素,如果该元素是Null,则发生NoSuchElementException

  2. removeLast():返回并移除队尾元素,如果该元素是Null,则发生NoSuchElementException

  3. pollFirst():返回并移除队头元素,如果队列无元素,则返回null

  4. pollLast():返回并移除队尾元素,如果队列无元素,则返回null

获取元素:

  1. getFirst():获取队头元素但不移除,如果队列无元素,则发生NoSuchElementException

  2. getLast():获取队尾元素但不移除,如果队列无元素,则发生NoSuchElementException

  3. peekFirst():获取队尾元素但不移除,如果队列无元素,则返回null

  4. peekLast():获取队尾元素但不移除,如果队列无元素,则返回null

栈操作:

pop():弹出栈中元素,也就是返回并移除队头元素,等价于removeFirst(),如果队列无元素,则发生NoSuchElementException。

push():向栈中压入元素,也就是向队头增加元素,等价于addFirst(),如果元素为null,则发生NoSuchElementException,如果栈空间受到限制,则发生lllegalStateException。

引用场景:

1、满足FIFO场景时。

2、满足LIFO场景时,曾经在解析XML按标签时使用过栈这种数据结构,但是却选择Stack类,如果在进行栈选型时,更推荐使用Deque类,因为Stack是线程同步。

3.3数据结构之数组和链表【记忆】

  • 数组结构

    查询快、增删慢

  • 队列结构

    查询慢、增删快

3.4ArrayDeque

概述:Deque接口的大小可变数组的实现。数组双端队列没有容量限制;它们可根据需要增加以支持使用。它们不是线程安全的;在没有外部同步时,它们不支持多个线程的并发访问。禁止null元素。此类很可能在用作堆栈时快于Stack,在用作队列时快于LinkedList。

特点:

  1. ArrayDeque是Deque接口的一种具体实现,是依赖于可变数组来实现的。

  2. ArrayDeque没有容量限制,可根据需求自动进行扩容

  3. ArrayDeque不支持值为null的元素。

  4. ArrayDeque可以作为栈来使用,效率要高于Stack

  5. ArrayDeque也可以作为队列来使用,效率相较于基于双向链表的LinkedList也要更好一些。

4.List集合的实现类

4.1List集合子类的特点【记忆】

  • ArrayList集合(可调整大小的数组的实现List接口。实现所有可选列表操作,并允许所有元素,包括null。除了实现List接口之外,该类还提供了一些方法来操纵内部使用的存储列表的数组的大小。这个类大致相当于Vector,不同之处在于它是不同步的)

    1.底层是数组结构实现,查询快、增删慢。默认初始长度为0。

    2.能够存储null值。

    3.线程不安全,效率高。

    4.底层是数组结构,那么就意味着查询和修改的效率高,而增加和删除的效率就低了。

    5.有索引,能够方便的检索。

    6.元素可以重复,我们可以自己通过选择排序法去重。

    7.不可排序。

    注:ArrayList中常用的方法全部来自于父类Collection,List,Object。

  • LinkedList集合

    1、底层是双向链表结构实现,元素有序,可重复。

    2、查询,修改慢、增删快。顺序访问会非常高效,而随机访问效率会比较低。

    3、LinkedList实现了List接口,支持使用索引访问元素。

    4、LinkedList实现Deque接口,所以LinkedList也可以当作双端队列使用。

    5、LinkedList是线程不安全的,效率高。

    双向链表特点:

    1、灵活的空间要求,存储空间不要求连续。

    2、不支持下标访问,支持顺序遍历。

    3、针对增删效率会高一些,只和操作节点的前后节点有关系,无需移动元素。

4.2LinkedList集合的特有功能【应用】

  • 特有方法

    方法名说明
    public void addFirst(E e)在该列表开头插入指定的元素
    public void addLast(E e)将指定的元素追加到此列表的末尾
    public E getFirst()返回此列表中的第一个元素
    public E getLast()返回此列表中的最后一个元素
    public E removeFirst()从此列表中删除并返回第一个元素
    public E removeLast()从此列表中删除并返回最后一个元素

4.3Vector接口

常用方法:

增加:1、void addElement(E obj) 添加元素obj到集合中。

2、void insertElementAt(E obj,int index) 在指定索引 index 处插入元素obj

删除:1、void removeElementAt(int index) 移除指定索引 index 处的元素。

2、void removeAllElements() 移除所有元素。

修改:1、void setElementAt(E obj,int index) 修改指定索引 index 的元素为obj。

遍历:1、for循环。

2、使用Enumeration迭代器遍历集合中的元素。

获取:1、firstElement() 获取集合中的第一个元素

2、lastElement() 获取集合中的最后一个元素

3、ElementAt(int index) 获取指定索引index的元素

特点:

1:底层数据结构是数组

2:有索引,能够方便检索

3:增加和删除效率低,查询和修改的效率高

4:线程安全,效率低

5:能够存储null

6:元素可重复

7:不可以排序

5.泛型

5.1泛型概述【理解】(在编译时就确定类型的一种技术)

  • 泛型的介绍

    泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制

  • 泛型的好处

    1. 把运行时期的问题提前到了编译期间

    2. 避免了强制类型转换

    3. 提高了程序的安全性

  • 泛型的定义格式

    • <类型>: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如: <E> <T>

    • <类型1,类型2…>: 指定多种类型的格式,多种类型之间用逗号隔开.例如: <E,T> <K,V>

    • 不能写基本数据类型

5.2泛型类【应用】

  • 定义格式

    修饰符 class 类名<类型> {  }
  • 示例代码

    • 泛型类

      public class Generic<T> {
          private T t;
      ​
          public T getT() {
              return t;
          }
      ​
          public void setT(T t) {
              this.t = t;
          }
      }

    • 测试类

      public class GenericDemo1 {
          public static void main(String[] args) {
              Generic<String> g1 = new Generic<String>();
              g1.setT("杨幂");
              System.out.println(g1.getT());
      ​
              Generic<Integer> g2 = new Generic<Integer>();
              g2.setT(30);
              System.out.println(g2.getT());
      ​
              Generic<Boolean> g3 = new Generic<Boolean>();
              g3.setT(true);
              System.out.println(g3.getT());
          }
      }

5.3泛型方法【应用】

  • 定义格式

    修饰符 <类型> 返回值类型 方法名(类型 变量名) {  }
  • 注意:普通方法可以使用方法声明的泛型或者类泛型。静态方法是不能使用在类名处声明的泛型。

  • 示例代码

    • 带有泛型方法的类

      public class Generic {
          public <T> void show(T t) {
              System.out.println(t);
          }
      }

    • 测试类

      public class GenericDemo2 {
          public static void main(String[] args) {
              Generic g = new Generic();
              g.show("柳岩");
              g.show(30);
              g.show(true);
              g.show(12.34);
          }
      }

5.4泛型接口【应用】

  • 定义格式

    修饰符 interface 接口名<类型> {  }
  • 示例代码

    • 泛型接口

      public interface Generic<T> {
          void show(T t);
      }

    • 泛型接口实现类1

      定义实现类时,定义和接口相同泛型,创建实现类对象时明确泛型的具体类型

      public class GenericImpl1<T> implements Generic<T> {
          @Override
          public void show(T t) {
              System.out.println(t);
          }
      }

    • 泛型接口实现类2

      定义实现类时,直接明确泛型的具体类型

      public class GenericImpl2 implements Generic<Integer>{
           @Override
           public void show(Integer t) {
                System.out.println(t);
           }
      }

    • 测试类

      public class GenericDemo3 {
          public static void main(String[] args) {
              GenericImpl1<String> g1 = new GenericImpl<String>();
              g1.show("林青霞");
              GenericImpl1<Integer> g2 = new GenericImpl<Integer>();
              g2.show(30);
            
              GenericImpl2 g3 = new GenericImpl2();
              g3.show(10);
          }
      }

5.5类型通配符(限定类型的范围,泛型不具备继承性,但是数据具备继承性)

  • 类型通配符: <?>(无界通配符)

    • ArrayList<?>: 表示元素类型未知的ArrayList,它的元素可以匹配任何的类型

    • 但是并不能把元素添加到ArrayList中了,获取出来的也是父类类型

  • 类型通配符上限: <? extends 类型>

    • ArrayListList <? extends Number>: 它表示的类型是Number或者其子类型

  • 类型通配符下限: <? super 类型>

    • ArrayListList <? super Number>: 它表示的类型是Number或者其父类型

  • 泛型通配符的使用

    public class GenericDemo4 {
        public static void main(String[] args) {
            ArrayList<Integer> list1 = new ArrayList<>();
            ArrayList<String> list2 = new ArrayList<>();
            ArrayList<Number> list3 = new ArrayList<>();
            ArrayList<Object> list4 = new ArrayList<>();
    ​
            method(list1);
            method(list2);
            method(list3);
            method(list4);
    ​
            getElement1(list1);
            getElement1(list2);//报错
            getElement1(list3);
            getElement1(list4);//报错
    ​
            getElement2(list1);//报错
            getElement2(list2);//报错
            getElement2(list3);
            getElement2(list4);
        }
      
        // 泛型通配符: 此时的泛型?,可以是任意类型
        public static void method(ArrayList<?> list){}
        // 泛型的上限: 此时的泛型?,必须是Number类型或者Number类型的子类
        public static void getElement1(ArrayList<? extends Number> list){}
        // 泛型的下限: 此时的泛型?,必须是Number类型或者Number类型的父类
        public static void getElement2(ArrayList<? super Number> list){}
    ​
    }

应用场景:

1、如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。

2、如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值