JavaSE学习笔记:集合框架、迭代器、泛型

文章目录

一、集合框架概述

1.Collection和Map

  • java.util.Collectionjava.util.Map
  • 集合按照存储结构可以分为两大类,分别是单列集合Collection和双列集合Map
  • 单列集合就可以按照字面意思理解为一列,双列就是有两列嘛key->value

2.Collection集合

在这里插入图片描述

  • 上述图片应该非常简单清晰明了的说明了Collection集合的结构和之间的区别
  • Collection是单列集合的根接口
  • 它有两个重要的子接口
    • java.util.List:元素有序可重复
    • java.util.Set:元素无序不可重复
  • 子接口下面就是具体的实现类,就是我们平时使用得最多的那几个

3.Collection集合常用方法

定义了单列集合的一些通用的方法,这些方法适用于上述所有的单例集合。注意每个方法的返回值。另外注意集合的使用过程中是一种多态形式,同一个接口由不同的实现类来实现。

  • public boolean add(E e): 把给定的对象添加到当前集合中 。
  • public void clear():清空集合中所有的元素。
  • public boolean remove(E e): 把给定的对象在当前集合中删除。
  • public boolean contains(E e): 判断当前集合中是否包含给定的对象。
  • public boolean isEmpty(): 判断当前集合是否为空。
  • public int size(): 返回集合中元素的个数。
  • public Object[] toArray(): 把集合中的元素,存储到数组中。

二、迭代器

java.util.Iterator 通用的取出集合中元素的方法。

1.常用方法

  • java.util.Iterator接口:迭代器(对集合进行遍历)
  • 有两个常用的方法
    • boolean hasNext() 如果仍有元素可以迭代,则返回 true。 判断集合中还有没有下一个元素,有就返回true,没有就返回false
    • E next() 返回迭代的下一个元素。 取出集合中的下一个元素

2.如何获取迭代器

  • Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊
  • Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象
  • Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。

3.使用步骤(掌握)

  • 1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
  • 2.使用Iterator接口中的方法hasNext判断还有没有下一个元素
  • 3.使用Iterator接口中的方法next取出集合中的下一个元素

4.使用实例

    public static void main(String[] args) {
        //创建一个集合对象
        Collection<String> coll = new ArrayList<>();
        //往集合中添加元素
        coll.add("姚明");
        coll.add("科比");
        coll.add("麦迪");
        coll.add("詹姆斯");
        coll.add("艾弗森");
        /*
            1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
            注意:
                Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
         */
        //多态  接口            实现类对象
        Iterator<String> iterator = coll.iterator();
        //遍历迭代器 获取元素
        //判断是否还有下一个元素
        while (iterator.hasNext()){
            //获取当前元素并且指针前移
            String e = iterator.next();
            System.out.println(e);
        }
    }

5.迭代器使用原理

在这里插入图片描述

三、增强型for循环(更常用)

用来遍历数组和集合。
底层实现就是迭代器,但是用了for循环的格式,简化了迭代器的书写。

1.简介

  • Collectionextends Iterable:所有的单列集合都可以使用增强for
  • public interface Iterable实现这个接口允许对象成为 “foreach” 语句的目标。
  • 增强for循环:用来遍历集合和数组
  • 格式:
    for(集合/数组的数据类型 变量名: 集合名/数组名){ sout(变量名); }

2.使用实例

  public static void main(String[] args) {
        demo02();
    }

    //使用增强for循环遍历集合
    private static void demo02() {
        ArrayList<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        for(String s : list){
            System.out.println(s);
        }
    }

    //使用增强for循环遍历数组
    private static void demo01() {
        int[] arr = {1,2,3,4,5};
        for(int i:arr){
            System.out.println(i);
        }
    }

3.注意点

  • 它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
  • 必须有被遍历的目标。目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现。

四、泛型

1.泛型的概念

在这里插入图片描述

2.使用泛型的好处

2.1使用集合对象,不使用泛型会带来的问题

2.1.1实例
 public static void main(String[] args) {
        show01();
    }
    private static void show01() {
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add(1);

        //使用迭代器遍历list集合
        //获取迭代器
        Iterator it = list.iterator();
        //使用迭代器中的方法hasNext和next遍历集合
        while(it.hasNext()){
            //取出元素也是Object类型
            Object obj = it.next();
            System.out.println(obj);

            //想要使用String类特有的方法,length获取字符串的长度;不能使用  多态 Object obj = "abc";
            //需要向下转型
            //会抛出ClassCastException类型转换异常,不能把Integer类型转换为String类型
            String s = (String)obj;
            System.out.println(s.length());
        }
    }
  • 运行报错

在这里插入图片描述

2.1.2注意点
  • 集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据
  • 想要使用String类特有的方法,length获取字符串的长度;不能使用 多态 Object obj = "abc";需要向下转型,但是这个转型并不是都能转。因为不清楚预知的类型
  • 会抛出ClassCastException类型转换异常,不能把Integer类型转换为String类型

2.2使用集合使用泛型

2.2.1实例
 public static void main(String[] args) {
        show02();
    }
    /*
       创建集合对象,使用泛型
       好处:
           1.避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
           2.把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)
        弊端:
           泛型是什么类型,只能存储什么类型的数据
    */
    private static void show02() {
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        //list.add(1);//add(java.lang.String)in ArrayList cannot be applied to (int)

        //使用迭代器遍历list集合
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s+"->"+s.length());
        }
    }
2.2.2注意点

在这里插入图片描述

3.定义和使用含有泛型的类

在这里插入图片描述

4.定义和使用含有泛型的方法

4.1定义方法

  • 定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间
  • 格式:
 修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
           方法体;
        }
  • 含有泛型的方法,在调用方法的时候确定泛型的数据类型
  • 传递什么类型的参数,泛型就是什么类型

4.2实例

在这里插入图片描述

5.定义和使用含有泛型的接口

5.1第一种使用方式

在这里插入图片描述

5.2第二种使用方式

在这里插入图片描述

6.泛型通配符

6.1基本使用:只能作为方法的参数使用

在这里插入图片描述

6.2不能创建对象使用

在这里插入图片描述

6.3泛型的上限限定和下限限定(了解)

  • 泛型的上限限定: ? extends E 代表使用的泛型只能是E类型的子类/本身
  • 泛型的下限限定: ? super E 代表使用的泛型只能是E类型的父类/本身
6.3.1上限

在这里插入图片描述

6.3.2下限

在这里插入图片描述

五、List集合

java.util.List接口继承了Collection接口

1、List接口的三大特点

  • 有序
  • 有索引,因此包含了一些带索引的方法
  • 元素允许重复(Set不允许重复)

2.List接口中带索引的方法(独有)

  • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
  • public E get(int index):返回集合中指定位置的元素。
  • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

2.1方法使用实例

public static void main(String[] args) {
        //创建一个list结合对象 多态
        List<String> list = new ArrayList<>();
        //添加元素
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("a");
        //打印集合
        //打印结果不是hashcode 说明重写了toString方法
        System.out.println(list);

        //指定位置上添加指定元素
        //public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
        list.add(3,"three");
        System.out.println(list);

        //移除指定位置的元素,返回值是被移除的元素
        String remove = list.remove(2);
        System.out.println("被移除的元素:" + remove);
        System.out.println(list);

        //指定元素替换集合中指定位置的元素,返回值是更新前的元素
        String setE = list.set(4, "four");
        System.out.println("被替换的元素为:" + setE);
        System.out.println(list);

        //List的遍历有三种方式
        //1.for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        System.out.println("-----------------");
        //2.迭代器
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("-----------------");
        //3.增强型for循环
        for (String s : list) {
            System.out.println(s);
        }
}

3.注意:操作索引的时候,一定要防止索引越界异常

  • IndexOutOfBoundsException:索引越界异常,集合会报
  • ArrayIndexOutOfBoundsException:数组索引越界异常
  • StringIndexOutOfBoundsException:字符串索引越界异常

4.ArrayList实现类

  • 大小可变的数组(动态数组)
  • 查询快,增删慢
  • 线程不同步,线程不安全

5.LinkedList实现类

5.1特点

  • 链表实现
  • 查询慢,增删快
  • 有大量的操作首尾元素的特有方法
  • 使用LinkedList时,创建对象不建议使用多态

5.2特有方法

  • public void addFirst(E e):将指定元素插入此列表的开头。

  • public void addLast(E e):将指定元素添加到此列表的结尾。

  • public void push(E e):将元素推入此列表所表示的堆栈。

  • public E getFirst():返回此列表的第一个元素。

  • public E getLast():返回此列表的最后一个元素。

  • public E removeFirst():移除并返回此列表的第一个元素。

  • public E removeLast():移除并返回此列表的最后一个元素。

  • public E pop():从此列表所表示的堆栈处弹出一个元素。

  • public boolean isEmpty():如果列表不包含元素,则返回true。

5.3使用实例

public class Demo02LinkedList {
    public static void main(String[] args) {
        show01();
        System.out.println("---------------");
        show02();
        System.out.println("---------------");
        show03();

    }


    /*
        - public void addFirst(E e):将指定元素插入此列表的开头。
        - public void addLast(E e):将指定元素添加到此列表的结尾。
        - public void push(E e):将元素推入此列表所表示的堆栈。此方法等效于 addFirst(E)。
     */
    private static void show01() {
        //创建LinkeeList对象
        LinkedList<String> linked = new LinkedList<>();
        //添加元素
        linked.add("a");
        linked.add("b");
        linked.add("c");
        System.out.println(linked);//[a, b, c]
        //将指定元素插入到开头
        linked.addFirst("first");
        System.out.println(linked);
        //指定元素插入到末尾
        linked.addLast("last");
        System.out.println(linked);
        //push等价于 addFirst
        linked.push("push is equal to the addFirst Method");
        System.out.println(linked);

    }
    /*
      - public E getFirst():返回此列表的第一个元素。
      - public E getLast():返回此列表的最后一个元素。
   */
    private static void show02() {
        //创建LinkeeList对象
        LinkedList<String> linked = new LinkedList<>();
        //添加元素
        linked.add("a");
        linked.add("b");
        linked.add("c");
        System.out.println(linked);//[a, b, c]

        String first = linked.getFirst();
        System.out.println(first);

        String last = linked.getLast();
        System.out.println(last);
    }

    /*
       - public E removeFirst():移除并返回此列表的第一个元素。
       - public E removeLast():移除并返回此列表的最后一个元素。
       - public E pop():从此列表所表示的堆栈处弹出一个元素。此方法相当于 removeFirst
    */
    private static void show03() {
        //创建LinkeeList对象
        LinkedList<String> linked = new LinkedList<>();
        //添加元素
        linked.add("a");
        linked.add("b");
        linked.add("c");
        System.out.println(linked);//[a, b, c]

        String s = linked.removeFirst();
        System.out.println("移除并返回:" + s);
        String s1 = linked.removeLast();
        System.out.println("移除并返回:" + s1);
        System.out.println(linked);
    }
    
}

6.Vector(了解)

  • 底层也是数组
  • 同步的,线程安全的

六、Set集合

java.util.Set接口 extends Collection接口

1.特点

  • 1.不允许存储重复的元素
  • 2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历

2.HashSet(常用来去重)

java.util.HashSet集合 implements Set接口

2.1特点

  • 1.不允许存储重复的元素
  • 2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
  • 3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
  • 4.底层是一个哈希表结构(查询的速度非常的快)

2.2使用实例

 public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        //使用add方法往集合中添加元素
        set.add(1);
        set.add(3);
        set.add(2);
        set.add(1);
        //使用迭代器遍历set集合
        Iterator<Integer> it = set.iterator();
        while (it.hasNext()){
            Integer n = it.next();
            System.out.println(n);//1,2,3
        }
        //使用增强for遍历set集合
        System.out.println("-----------------");
        for (Integer i : set) {
            System.out.println(i);
        }
    }

3.哈希值

3.1对象哈希值的获取

  • 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)
  • 在Object类有一个方法,可以获取对象的哈希值
  • hashCode方法的源码:
    • public native int hashCode();
    • native:代表该方法调用的是本地操作系统的方法
      在这里插入图片描述

3.2重写hashcode()方法

在这里插入图片描述

3.3toString方法

return getClass().getName() + "@" + Integer.toHexString(hashCode());
在这里插入图片描述

3.4String类的hashcode()方法

在这里插入图片描述

4.HashSet集合存储数据的结构

  • jdk1.8版本之前:哈希表=数组加链表
  • jdk1.8版本之后:
    • 哈希表=数组+链表
    • 哈希表=数组+红黑树

在这里插入图片描述

5.HashSet不允许存储重复元素的原理

5.1现象观察

在这里插入图片描述

5.2原理分析

在这里插入图片描述

5.3小结

  • HashSet对象在调用add方法的时候,做了两件事
  • 首先计算待存储对象的hashcode,并且在哈希表中查找是否存在该hashcode
    • 如果不存在该hashcode,则把待存储对象添加到哈希表中
    • 如果存在该hashcode,那么就会比较该哈希表中该hashcode位置上已经存储的元素是否和待存储元素相同,如果相同则不会存储,如果不同则会存储。(疑问:如果该hashcode上的元素已经很多了,这个时候需要一一比对,是否会降低效率?如果是,源码是如何解决这个问题的?)

6.HashSet存储自定义类型元素

自定义的类必须重新equals方法和hashcode方法,才能实现存储的元素唯一

6.1自定义类没有重写equal和hashcode方法

在这里插入图片描述

6.2自定义类重写equal和hashcode方法

在这里插入图片描述

7.LinkedHashSet

继承了 HashSet
java.util.LinkedHashSet集合 extends HashSet集合
LinkedHashSet集合特点:

  • 底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序
  • 有序,无重复

在这里插入图片描述

七、可变参数

1.场景引入

  • 如果我需要一个方法来计算多个整数
  • 但是我事先无法知道要计算多少个整数的和
  • 这个时候可以用可变参数来解决这个问题

2.基本原理和使用

  • 可变参数:是JDK1.5之后出现的新特性
  • 使用前提:
    • 当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数.
  • 使用格式:定义方法时使用
    • 修饰符 返回值类型 方法名(数据类型...变量名){}
  • 可变参数的原理:
    • 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
    • 传递的参数个数,可以是0个(不传递),1,2…多个

2.1使用实例

在这里插入图片描述

3. 可变参数的注意事项

  • 1.一个方法的参数列表,只能有一个可变参数
  • 2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾
    在这里插入图片描述

4.可变参数的特殊写法(某些源码)

在这里插入图片描述

八、Collections集合工具类

注意CollectionCollection集合的根接口,而Collections是工具类,是用来操作集合的一组工具方法

1.往集合添加多个元素和打乱顺序

  • java.utils.Collections是集合工具类,用来对集合进行操作。部分方法如下:
    • public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
    • public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
      在这里插入图片描述

2.sort方法

2.1基本使用

在这里插入图片描述

2.2对自定义类型的元素排序、Comparable接口

public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。

  • 被排序的集合里边存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序的规则
  • 自己(this)-参数:升序

在这里插入图片描述

3.Comparator排序

public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。

3.1 Comparator和Comparable的区别

  • Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较的规则compareTo方法
  • Comparator:相当于找一个第三方的裁判,比较两个
  • Comparator的排序规则:o1-o2:升序

3.2java原生数据类型的排序

在这里插入图片描述

3.3 自定义类型排序(按单个属性)

在这里插入图片描述

3.4组合排序

在这里插入图片描述

九、Map集合

1特点

  • 1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
  • 2.Map集合中的元素,key和value的数据类型可以相同,也可以不同
  • 3.Map集合中的元素,key是不允许重复的,value是可以重复的
  • 4.Map集合中的元素,key和value是一一对应

2.常用接口

2.1HashMap

java.util.HashMap<k,v>集合 implements Map<k,v>接口

  • 1.HashMap集合底层是哈希表:查询的速度特别的快
    • JDK1.8之前:数组+单向链表
    • JDK1.8之后:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度
  • 2.hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致

2.2LinkedHashMap

java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合

  • 1.LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
  • 2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的

3.常用方法

  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
    • 存储键值对的时候,key不重复,返回值V是null
    • 存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
  • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
  • public V get(Object key)根据指定的键,在Map集合中获取对应的值。
    • key存在,返回对应的value值
    • key不存在,返回null
  • boolean containsKey(Object key)判断集合中是否包含指定的键。

4.遍历方法1(keySet):通过键找值进行遍历

  • 通过mapkeySet()方法获取map中所有的key并存储在一个set
  • 那么接下来遍历这个set即可
    • 迭代器
    • 增强型for循环

4.1使用实例

  public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        //1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
        Set<String> set = map.keySet();

        //2.遍历set集合,获取Map集合中的每一个key
        //使用迭代器遍历Set集合
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }

5.遍历方法2(entrySet()):使用Entry对象遍历

  • Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。
  • 然后再遍历这个set
  • Entry对象提供了两个方法getKey()getValue()

5.1使用实例

  public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);
        //2.获取entrySet对象
        Set<Map.Entry<String, Integer>> set = map.entrySet();
        //3.遍历set
        Iterator<Map.Entry<String, Integer>> iterator = set.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> next = iterator.next();
            System.out.println(next.getKey() + "=" + next.getValue());
        }
    }

6.HashMap存储自定义类型的键值对

6.1自定义类型作为value的时候

使用上没有限制

6.2自定义类型作为key的时候

由于必须保证key的唯一性,所以自定义类必须重写hashcodeequals方法

7.LinkedHashMap

记住有序即可
在这里插入图片描述

8.HashTable

  • 底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
  • HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
  • HashMap集合(之前学的所有的集合):可以存储null值,null键
  • Hashtable集合,不能存储null值,null键
  • Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
  • Hashtable的子类Properties依然活跃在历史舞台
  • Properties集合是一个唯一和IO流相结合的集合
    public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        map.put(null,"a");
        map.put("b",null);
        map.put(null,null);
        System.out.println(map);//{null=null, b=null}

        Hashtable<String,String> table = new Hashtable<>();
        //table.put(null,"a");//NullPointerException
        //table.put("b",null);//NullPointerException
        table.put(null,null);//NullPointerException

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值