0
点赞
收藏
分享

微信扫一扫

java集合(详细)


1、概述:

          在java中,集合类和集合接口都是在java.util包下。它们提供了一种更灵活、动态底管理数据的方式,相对于定长的数组,集合可以根据动态扩展和缩减大小。这样可以更有效地利用内存空间,避免了固定长度数据的限制。

集合框架中的各种实现类和接口可以根据需求选择,从而更好地满足不同场景下的数据存储和操作。

2、集合、数组的区别:

       1、动态性:集合具有动态性,可以根据需要动态增加和减少元素个数,而数组的长度是固定的,一旦创建就无法修改。

         2、类型:数组可以是基本数据类型的数组,也可以是对象数组,但是将建的时必须指定数组的类型和长度。而集合可以存储任意类型的对象,且长度可以变化。

           3、内存管理:数组时一个来纳许的内存快,一旦创建,长度是固定的,可能会导致内存的浪费和不足,而集合可以根据需要动态调整。

            4.、数组可以包含任何类型的元素,但在编译时无法检测元素的类型,容易导致类型转换错误,而集合框架支持泛型,在编译时强制检测元素的类型,减少类型错误的可能性。

3、Collection集合(单例集合的顶层接口,不直接使用)

3.1、 Collection集合的的常用方法

方法名

说明

boolean add(E e)

添加元素到集合的末尾(追加)

boolean remove(Object o)

删除指定的元素,成功则返回true(底层调用equles)

void clear()

清空集合

boolean contains(Object o)

判断元素在集合中是否存在,存在则返回true(底层调用equles)

boolean isEmpty()

判断集合是否为空,空则返回true

int size()

返回集合中元素个数

import java.util.ArrayList;
import java.util.Collection;

/**
 * 演示集合的基本操作
 */
public class CollectionDemo {
    public static void main(String[] args) {
        // 使用父类的引用指向子类的对象,形成多态
        Collection<String> con = new ArrayList<>();

        // 向集合中追加元素
        con.add("东邪");
        con.add("西毒");
        con.add("南帝");
        con.add("北丐");
        con.add("中神通");

        // 删除元素,通过元素名称删除
        System.out.println("删除元素:" + con.remove("西毒"));

        // 判断集合中是否包含指定参数元素
        System.out.println("是否包含'西毒':" + con.contains("西毒"));  // false
        System.out.println("是否包含'东邪':" + con.contains("东邪"));  // true

        // 获取集合中元素个数
        System.out.println("集合大小:" + con.size());

        // 判断集合是否为空
        System.out.println("集合是否为空:" + con.isEmpty()); // false

        // 清空集合
        con.clear();

        // 再次判断集合是否为空
        System.out.println("清空后集合是否为空:" + con.isEmpty()); // true
        System.out.println("清空后的集合:" + con); // 打印空集合
    }
}

3.2、Collection集合的遍历

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class MyCollectionTraversal {
    public static void main(String[] args) {
        // 使用ArrayList实现Collection接口,形成多态
        Collection<String> myCollection = new ArrayList<>();
        
        // 向集合中添加元素
        myCollection.add("苹果");
        myCollection.add("香蕉");
        myCollection.add("橙子");
        myCollection.add("葡萄");
        
        // 使用增强型for循环遍历集合
        System.out.println("使用增强型for循环遍历集合:");
        for (String fruit : myCollection) {
            System.out.print(fruit + "\t");
        }
        System.out.println(); // 换行
        
        // 使用迭代器遍历集合
        System.out.println("使用迭代器遍历集合:");
        Iterator<String> iterator = myCollection.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + "\t");
        }
        System.out.println(); // 换行
    }
}

3.3、 ArrayList构造和添加方法

方法名

说明

public ArrayList<E>()

创建一个空集合

public boolean add(E e)

将指定的参数元素追加到集合的末尾

public void add(int index ,E e)

在集合的指定位置添加指定的元素(插入元素)

public void addAll(E object)

用于将指定集合中所有元素添加到当前集合中

/**
 * 演示ArrayList的构造和添加方法
 */
public class MyArrayList {
    public static void main(String[] args) {
        // 创建空ArrayList
        ArrayList<String> myList = new ArrayList<>(); // 使用String作为泛型

        // 采用默认追加的方式添加元素
        System.out.println("添加 '成龙' 是否成功:" + myList.add("成龙"));
        System.out.println("添加 '李连杰' 是否成功:" + myList.add("李连杰"));
        System.out.println("添加 '周星驰' 是否成功:" + myList.add("周星驰"));
        System.out.println("添加 '梁朝伟' 是否成功:" + myList.add("梁朝伟"));

        // 插入的方式添加元素
        myList.add(1, "张曼玉"); // 指定位置插入元素,索引位置之后的元素会自动向后移动

        // 创建新的ArrayList
        ArrayList<String> newList = new ArrayList<>();
        newList.add("巩俐");
        newList.add("章子怡");
        newList.add("刘德华");
        newList.add("周杰伦");

        // 查看集合中的元素
        System.out.println("原集合内部元素:" + myList);
        System.out.println("新集合内部元素:" + newList);

        // 将新集合全部元素添加到原集合中
        myList.addAll(newList);
        System.out.println("合并后的集合内部元素:" + myList);
    }
}

3.4、ArrayList实现原理

  1. 内部使用一个 Object 数组来存储元素。
  2. 当数组空间不足以容纳新的元素时,会自动扩容。扩容时通常会创建一个新的更大的数组,并将原数组中的元素拷贝到新数组中。
  3. 当数组中元素数量减少到一定程度时,会自动缩减数组的大小,以节省内存空间。
  4. ArrayList 支持随机访问,通过索引来直接访问元素,因为底层是基于数组实现的

public class MyArrayList<E> {
    private static final int DEFAULT_CAPACITY = 10; // 默认初始容量
    private Object[] elements; // 存储元素的数组
    private int size; // 元素数量

    public MyArrayList() {
        elements = new Object[DEFAULT_CAPACITY]; // 初始化数组
        size = 0; // 初始元素数量为0
    }

    // 添加元素
    public void add(E element) {
        ensureCapacity(); // 确保容量足够
        elements[size++] = element; // 将元素放入数组中,并增加元素数量
    }

    // 获取指定索引的元素
    public E get(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); // 索引越界检查
        return (E) elements[index]; // 返回指定索引处的元素
    }

    // 确保容量足够
    private void ensureCapacity() {
        if (size == elements.length) { // 如果当前元素数量等于数组长度
            int newCapacity = elements.length * 2; // 扩容为原来的两倍
            Object[] newElements = new Object[newCapacity]; // 创建新数组
            System.arraycopy(elements, 0, newElements, 0, size); // 将原数组元素复制到新数组
            elements = newElements; // 更新数组引用
        }
    }

    // 返回列表大小
    public int size() {
        return size;
    }
}

4、hashMap

双列集合:用来存储键值对的集合。

  • interface Map<K,V> : K(key)键 ,V(value)值
  • 将键映射到值的对象,不能出现重复的键,每个键最多可以映射到一个值

1、Map和Collection没有继承关系。 2、Map集合以key和value的方式存储数据:键值对 key和value都是引用数据类型。 key和value都是存储对象的内存地址。 key起到主导的地位,value是key的一个附属品。

4.1Map的基本方法

方法名

说明

V put(K key,V value)

设置键值对

V remove(Object key)

删除元素

void clear()

清空集合

boolean containsKey(Object key)

判断键是否存在,存在则返回true

boolean containsValue(Object value)

判断值是否存在,存在则返回true

boolean isEmpty()

判断集合是否为空

int size()

获取集合元素个数

import java.util.HashMap;
import java.util.Map;

public class SimpleMapExample {
    public static void main(String[] args) {
        // 创建一个HashMap实例
        Map<String, Integer> map = new HashMap<>();

        // 设置键值对
        map.put("apple", 10);
        map.put("banana", 20);
        map.put("orange", 15);

        // 删除元素
        map.remove("banana");

        // 清空集合
        map.clear();

        // 判断键是否存在
        boolean containsKey = map.containsKey("apple");
        System.out.println("Contains key 'apple': " + containsKey);

        // 判断值是否存在
        boolean containsValue = map.containsValue(20);
        System.out.println("Contains value 20: " + containsValue);

        // 判断集合是否为空
        boolean isEmpty = map.isEmpty();
        System.out.println("Is map empty: " + isEmpty);

        // 获取集合大小
        int size = map.size();
        System.out.println("Map size: " + size);
    }
}

4.2HashMap原理


HashMap 在 JDK1.8 之前的实现方式 数组+链表,

但是在 JDK1.8 后对 HashMap 进行了底层优化,改为了由 数组+链表或者数值+红黑树

实现,主要的目的是提高查找效率


java集合(详细)_java

 

 

1. Jdk8 数组+链表或者数组+红黑树实现,当链表中的元素超过了 8 个以后, 会

将链表转换为红黑树,当红黑树节点 小于 等于 6 时又会退化为链表。

2. 当 new HashMap():底层没有创建数组,首次调用 put()方法示时,底层创建长度

为 16 的数组,jdk8 底层的数组是:Node[],而非 Entry[],用数组容量大小乘以加载因子得

到一个值,一旦数组中存储的元素个数超过该值就会调用 rehash 方法将数组容量增加到原

来的两倍,专业术语叫做扩容,在做扩容的时候会生成一个新的数组,原来的所有数据需要

重新计算哈希码值重新分配到新的数组,所以扩容的操作非常消耗性能.

默认的负载因子大小为 0.75,数组大小为 16。也就是说,默认情况下,那么当 HashMap

中元素个数超过 16*0.75=12 的时候,就把数组的大小扩展为 2*16=32,即扩大一倍。

3. 在我们 Java 中任何对象都有 hashcode,hash 算法就是通过 hashcode 与自己进

行向右位移 16 的异或运算。这样做是为了计算出来的 hash 值足够随机,足够分散,还有

产生的数组下标足够随机,

map.put(k,v)实现原理

(1)首先将 k,v 封装到 Node 对象当中(节点)。

(2)先调用 k 的 hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。

(3)下标位置上如果没有任何元素,就把 Node 添加到这个位置上。如果说下标对应的位

置上有链表。此时,就会拿着 k 和链表上每个节点的 k 进行 equal。如果所有的 equals 方

法返回都是 false,那么这个新的节点将被添加到链表的末尾。如其中有一个 equals 返回了

true,那么这个节点的 value 将会被覆盖。

map.get(k)实现原理

(1)、先调用 k 的 hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。

(2)、在通过数组下标快速定位到某个位置上。重点理解如果这个位置上什么都没有,则返

14回 null。如果这个位置上有单向链表,那么它就会拿着参数 K 和单向链表上的每一个节点

的 K 进行 equals,如果所有 equals 方法都返回 false,则 get 方法返回 null。如果其中一

个节点的 K 和参数 K 进行 equals 返回 true,那么此时该节点的 value 就是我们要找的 value

了,get 方法最终返回这个要找的 value。

写在最后:

                本篇文章主要是博主工作中个人的一下理解,记录工作中常用集合的使用方式、优点和用途,希望大家可以根据本文有一个了解。

 

举报

相关推荐

0 条评论