集合 框架

集合的概述

集合(容器)

程序存储数据方式 :

  • 变量:单一的数据

  • 数组:一组具有相同数据类型的数据

    • 问题1:元素的数据类型相同

    • 问题2:长度定义后,不可更改

  • 对象:一组具有关联性的数据(变向解决了数组的问题1)

    存储学生(Student)数据:创建学生对象,存储学生姓名、年龄、身高、体重

    存储多个学生数据:Student[]

  • 集合:

    • 丰富且强大的数据存储(Java 提供的很多 API )

集合体系结构

在 java.utll 包(工具)。

Collection:存储的是可重复(不唯一)、无序的数据

  • 接口List :存储的是可重复(不唯一),有序的数据

    使用接口需要找其的实现类

    • ArrayList

    • LinkedList

    • .....

  • 接口Set : 存储的是不可重复(唯一),无序的数据

    • HashSet

    • TreeSet

    • .....

接口 Map :存储的是键值对(key键-value键,键和值一一对应)数据

  • HashMap

  • HashTable

    • Properties

  • TreeMap

  • ......

list集合

ArrayList(动态数组)

需求:存储3个新闻数据,新闻数据包含:标题、作者、时间、内容、阅读数。

构造方法

  • ArrayList <泛型/E> ()

  • 常用方法:

    • add(E e) : boolean 存储指定类型(E:泛型类型)的元素

    • add(int index, E element) : void 在指定下标位置存储指定类型的元素,原有位置的元素会依次后移

    • remove(int index) : E 删除指定下标位置的元素,返回被删除的元素

    • remove(Object obj) : boolean 删除指定的元素(如果有重复的,只会删除第一个找到的元素)

    • set(int index, E element) : E 修改指定下标位置的元素,返回被替换的元素

    • get(int index) : E 根据下标查询元素

    • size() : int 查询集合中存储的元素数量

    • contains(Object o) : boolean 判断集合中是否存在指定的元素

    • indexOf(Object o) : int 查询指定元素在集合中的下标,找不到会返回 -1

    • lastIndexOf(Object o) : int 从后往前查找指定元素在集合中的下标,找不到会返回-1

      注意:从后往前查找,只不过是方向变化,下标还是正向的下标(不会变!)

    • clear() : void 清空集合

    • isEmpty() : boolean 判断集合是否是空的(没有一个元素)

LinkedList

构造方法:

  • LinkedList<E>()

常用方法:

  • addFirst(E e) : void 向前追加元素

  • addLast(E e) : void 向后追加元素

  • removeFirst() : E 删除第一个元素

  • removeLast() : E 删除最后一个元素

  • getFirst() : E 查询第一个元素

  • getLast() : E 查询最后一个元素

  • ....

其他方法略,大多和 ArrayList 一致,因为这些方法都是定义在 List 接口中,所以同为 List 接口实现类,当然都会重写相应的方法。

注意:方法名虽然相同,代表的只是方法功能一致,但不代表实现一致!

例如:add()、remove() ....

ArrayList和LinkedList的区别(面试题)

相同点:

  • 都是 List 接口的实现类,可以存储可重复的,有序的数据

不同点:

  • ArrayList 底层数据结构是数组结构,在实现数据的查询时,因为数组结构有下标,所以效率较高。但是,在增加或删除数据时,因为数组结构长度不可变,所以会创建一个新的数组,导致效率较低。

    它适合于查询较多,增删较少的情况。

  • LinkedList 底层数据结构是链表结构,在增加或删除数据时,尤其是首尾的增删,因为链表结构增加节点或删除节点,只需要修改下一个连接的地址即可,效率较高。但是,在实现数据的查询时,没有下标,只能从首节点依次进行查询,效率较低。

    它适合于增删较多,查询较少的情况。

Set集合

HashSet

构造方法:

  • HashSet<E>()

常用方法:

  • add(E e) : boolean 存储元素(去重数据)

  • remove(E e) : E 删除数据

  • size() : int 获取集合的元素数量

  • contains(Object o) : boolean 判断是否包含指定的元素

  • ...

因为 Set 和 List 都是继承自 Collection 接口,所以很多方法也是相同的。

注意: 如果用 Set 存储引用数据类型数据,需要重写相应类的 equals 和 hashCode 方法。不然,不认为是重复数据,不会去重。

集合的遍历

List集合遍历

  1. 循环下标实现

    例如:遍历新闻数据

    for (int i = 0; i < list.size(); i++) {
        News news = list.get(i);
        System.out.println(news);
    }

  2. 增强 for 实现

    例如:遍历新闻数据

    for (News news : list) {
        System.out.println(news);
    }

  3. 迭代器

    // 迭代器:Iterator
    // iterator() : Iterator<E>
    Iterator<News> iterator = list.iterator();
    // hasNext() : boolean 判断是否还有下一个元素
    // next() : E 取出下一个元素
    //      if (iterator.hasNext()) {
    //          News next = iterator.next();
    //          System.out.println(next);
    //      }
    ​
    while (iterator.hasNext()) {
        News next = iterator.next();
        System.out.println(next);
    }

Set集合遍历

  1. 增强 for 实现

    for (News news : newsSet) {
        System.out.println(news);
    }

  2. 迭代器

    Iterator<News> iterator = newsSet.iterator();
    while (iterator.hasNext()) {
        News next = iterator.next();
        System.out.println(next);
    }

泛型

泛型:给集合限制元素的类型。

泛型是在 JDK 1.5 出现的特性。

它可以有效解决类型转换问题。

泛型都可以用在:

  • 类上

    // 集合
    public class ArrayList<E> {
        
    }
    // 在创建集合对象时,只要指定了 E 的具体类型,那么 add 方法的参数或返回值也就指定了对应的类型
    ​
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    ​
    public E remove(int index) {
        
    }

  • 方法上

    // Arrays类的方法
    // 在调用该方法时,传入什么类型数据,返回的就是什么类型的数据
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    在方法参数中出现了 ... ,它被称为可变参数,比较灵活。

    它意味着,你传递多少个指定类型的参数都可以,0个,1个,2个....

    可以把它在处理时看作是一个数组来处理。

    public class Demo03 {
    ​
    public static void main(String[] args) {
      //        printNames();
      printNames("张三", "李四", "王五");
    }
    ​
    public static void printNames(String... names) {
      for (String name : names) {
          System.out.println(name);
      }
    }
    ​
    }

  • 泛型还可以限制类型必须是某个类型的子类

    <? extends 类型>

泛型使用任何符号代表都可以。这些符号就是一个某种类型的表示。

常见的符号:

  • E(Element,元素)

  • T(Type,类型)

  • K(Key,键)

  • V(Value,值)

  • ....


泛型在指定具体类型时,必须是引用数据类型。

  • String

Java给基本类型都准备了相应的引用类型(基本类型相应的包装类型)

  • byte -> Byte

  • short -> Short

  • int -> Integer

  • long -> Long

  • float -> Float

  • double -> Double

  • char -> Character

  • boolean -> Boolean

Map集合概述

Map 集合是一种键值对数据的存储方案。

key-value,其中 key 是唯一的 ,而 value 是可以重复的。

Map 是无序存储(Hash)。

Map集合使用

  • HashMap

  • HashTable

    • Properties

  • TreeMap


构造方法:

  • HashMap<K, V>()

常用方法:

  • put(K key, V value) : V 存储/更新(相同键再次调用该方法)键值对数据,返回被替换的值(如果是存储,那么返回的是 null)

  • get(Object key) : V 根据键获取值

  • size() : int 获取集合中存储的键值对数量

  • containsKey(Object key) : boolean 判断集合中是否包含指定的键

  • containsValue(Object value) : boolean 判断集合中是否包含指定的值

  • remove(Object key) : V 根据键删除,返回的是被删除的值

  • keySet() : Set<K> 获取所有键的集合(键是唯一的,所以是Set集合)

  • entrySet() : Set<Entry<K, V>> 获取所有键值对的集合

    • Entry:

      • getKey() : K 获取 Entry 中的键

      • getValue() : V 获取 Entry 中的值

  • values() : Collection<V> 获取所有值的集合(Map存储,值是无序的,但是可重复,所以是Collection集合)

  • clear() : void 清空集合中的键值对

  • ...

Map集合的遍历

  1. 获取所有的键,遍历键根据键获取值

    Set<String> keySet = map.keySet();
    for (String key : keySet) {
        String value = map.get(key);
        System.out.println(key + "=" + value);
    }

  2. 获取所有键值对,遍历键值对,从中获取键和值

    Set<Entry<String,String>> entrySet = map.entrySet();
    for (Entry<String, String> entry : entrySet) {
        String key = entry.getKey();
        String value = entry.getValue();
        System.out.println(key + "=" + value);
    }

  3. forEach方法(1.8)

    map.forEach((key, value) -> {
        System.out.println(key + "=" + value);
    });

Collections工具类

Arrays。

Collection 和 Collections 的区别?(面试题)

  • Collection 是一个集合的顶级接口,用于存储可重复的,无序的数据

  • Collections 是一个集合的工具类,里面定义了大量的静态方法,用于更为便捷的操作集合

常用方法:

  • sort(List<T> list) : void 可以实现对集合的升序排序

  • min(Collection<? extends T> coll) : T 获取集合中的最小值

  • max(Collection<? extends T> coll) : T 获取集合中的最大值

  • reverse(List<?> list) : void 反转集合元素

  • shuffle(List<?> list) : void 打乱集合元素

ArrayList的扩容原理(面试题)

定义时,首先进行定义一个空数组 Object[] elementDate = {}; ,在存储数据时,首先进行数据存储 elementDate[0] = "xx",再进行size的增加

默认初始化容量为:10(数组)

扩容时,会扩容为原来的1.5倍。

默认仅仅创建集合对象,不存储: 内部的数组会初始化为一个静态常量(空数组)

默认的初始化容量: 10(长度为10的数组)

进行扩容时,每次扩容: 1.5 倍


集合初始化时, 指定集合初始值大小:

如果确定集合要存储的元素个数,那么 ArrayList 在创建对象时,建议指定 initialCapacity 为你要存储的元素个数。

ArrayList<Integer> list = new ArrayList<>(3);

HashMap 使用 HashMap(int initialCapacity) 初始化,如果暂时无法确定集合大小, 那么指定默认值( 16) 即可。 正例: initialCapacity = (需要存储的元素个数 / 负载因子) + 1 。 注意负载因子(即 loader factor) 默认 为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值) 。

HashMap<String, String> map = new HashMap<>(16);

参见阿里巴巴开发手册要求。

第三方的工具:Hutool

概述

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

Hutool中的工具方法来自每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;

Hutool的设计思想是尽量减少重复的定义,让项目中的util这个package尽量少,总的来说有如下的几个思想:

  • 方法优先于对象

  • 自动识别优于用户定义

  • 便捷性与灵活性并存

  • 适配与兼容

  • 可选依赖原则

  • 无侵入原则

官网:https://www.hutool.cn/

安装(导入jar包)

  1. 下载 jar 包 hutool-all

  2. 在项目中新建一个目录:lib

  3. 拷贝 jar 包到 lib 目录

  4. 右键 jar 包 -> Build Path -> add to build path

  5. 在项目中会出现一个 Referenced Libraries 关联库

  6. 然后按照 Hutool 官方的入门API 文档使用即可

使用

集合工具类:

  • CollectionUtil

    • newArrayList(T... values) : ArrayList<T> 快速创建一个指定容量的集合

    • join(Iterable<T> iterable, CharSequence conjunction) : String 将集合中的元素通过指定字符拼接为字符串

    • union(Collection<T> coll1, Collection<T> coll2) : Collection<T> 取两个集合的并集

    • ....

  • MapUtil

    • newHashMap(int size) : HashMap<K, V> 快速创建一个指定容量的Map集合(它会自动帮我们算好初始化容量)

    • ...

随机数工具类:

  • RandomUtil

    • randomInt(int min, int max) : int 生成 [min, max) 范围的随机整数

    • randomNumbers(int length) : String 生成指定长度的随机字符串(整数)

    • ...

字符串工具类:

  • StrUtil

    • format(CharSequence template, Object... params) : String

      String format2 = StrUtil.format("我的姓名:{},我的年龄:{},我的余额:{}", name, age, money);
      System.out.println(format2);

    • isNotEmpty(CharSequence str) : boolean 判断字符串是否不为空(null、""空字符串)

    • ....

....