六,Java集合

bjynjj / 2024-10-19 / 原文

Java Collection集合

Collection【接口】

  • List【接口】:

    • 特点: 有序集合,允许重复元素,可以通过索引访问元素。
    • 子类:
      • ArrayList:
        • 底层数据结构: 动态数组。
        • 性能特点:
          • 查询操作(如get(index))时间复杂度为O(1)。
          • 增删操作(如add, remove)时间复杂度为O(n),因为可能需要移动数组中的元素。
          • 线程安全: 不是线程安全的,如果需要在多线程环境下使用,需要额外的同步措施。
          • 效率: 由于数组的连续内存分配,它提供了较高的效率。
      • Vector:
        • 底层数据结构: 动态数组。
        • 性能特点:
          • 与ArrayList类似,但所有公共方法都是同步的,因此是线程安全的。
          • 效率: 由于同步,效率比ArrayList低。
      • LinkedList:
        • 底层数据结构: 双向链表。
        • 性能特点:
          • 增删操作(如add, remove)时间复杂度为O(1),因为不需要移动元素。
          • 查询操作(如get(index))时间复杂度为O(n),因为需要遍历链表。
          • 线程安全: 不是线程安全的,如果需要线程安全的链表,可以考虑使用Collections.synchronizedList包装一个LinkedList。
  • Set【接口】:

    • 特点: 不允许重复元素,主要用于存储唯一元素的集合。
    • 子类:
      • HashSet:
        • 底层数据结构: 哈希表。
        • 性能特点:
          • 基于哈希表实现,元素的添加、删除和查找操作时间复杂度为O(1)。
          • 元素唯一性: 通过hashCode()和equals()方法来保证元素的唯一性。
          • 线程安全: 不是线程安全的,需要额外同步措施。
      • LinkedHashSet:
        • 底层数据结构: 哈希表和双向链表。
        • 性能特点:
          • 继承自HashSet,同时维护了一个双向链表来记录插入顺序。
          • 保持了HashSet的性能特点,同时提供了有序性。
      • TreeSet:
        • 底层数据结构: 红黑树。
        • 性能特点:
          • 元素自动排序,可以自定义排序规则。
          • 插入、删除和查找操作的时间复杂度为O(log(n))。
          • 元素唯一性: 通过比较器(Comparator)或元素的自然排序(Comparable)来保证。

示例代码

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;

public class CollectionExample {
    public static void main(String[] args) {
        // ArrayList 示例
        List<String> arrayList = new ArrayList<>();
        arrayList.add("Apple");
        arrayList.add("Banana");
        System.out.println(arrayList.get(0)); // 输出: Apple

        // LinkedList 示例
        List<String> linkedList = new LinkedList<>();
        linkedList.add("Orange");
        linkedList.add("Mango");
        linkedList.addFirst("Grape"); // 在开头添加元素
        System.out.println(linkedList.peek()); // 输出: Grape

        // HashSet 示例
        Set<String> hashSet = new HashSet<>();
        hashSet.add("Apple");
        hashSet.add("Banana");
        System.out.println(hashSet.contains("Apple")); // 输出: true

        // LinkedHashSet 示例
        Set<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("Orange");
        linkedHashSet.add("Mango");
        System.out.println(linkedHashSet); // 输出: [Orange, Mango]

        // TreeSet 示例
        Set<String> treeSet = new TreeSet<>();
        treeSet.add("Apple");
        treeSet.add("Banana");
        System.out.println(treeSet); // 输出: [Apple, Banana],已排序
    }
}

总结

  • List 接口提供了有序集合的实现,支持通过索引访问元素,适合需要保持元素顺序的场景。
  • Set 接口保证集合中元素的唯一性,适合需要去除重复元素的场景。
  • ArrayListLinkedList 提供了List接口的两种不同实现,各有优势,选择时需考虑操作类型和性能需求。
  • HashSetLinkedHashSet 提供了Set接口的两种不同实现,其中LinkedHashSet保持了元素的插入顺序。
  • TreeSet 提供了自动排序的Set实现,适合需要对元素进行排序的场景。

Java Map集合

Map【接口】

  • 概述:

    • 元素构成: Map集合中的元素是由键值对(key-value pairs)构成的。
    • 用途: 用于存储键值映射关系,通过键可以快速检索到对应的值。
  • 子类:

    • HashMap:
      • 特点:
        • 底层数据结构: 哈希表。
        • 唯一性: 键是唯一的,不允许重复。
        • 排序: 无序的,不保证元素的顺序。
        • 线程安全: 不是线程安全的,如果需要线程安全的Map,可以使用Collections.synchronizedMap方法或ConcurrentHashMap
        • 性能: 查询、插入和删除操作的平均时间复杂度为O(1),但最坏情况下可能退化为O(n)。
    • TreeMap:
      • 特点:
        • 底层数据结构: 红黑树。
        • 唯一性: 键是唯一的,不允许重复。
        • 排序: 根据键的自然顺序或构造时提供的Comparator进行排序。
        • 线程安全: 不是线程安全的,如果需要线程安全的TreeMap,可以考虑使用Collections.synchronizedSortedMap方法。
        • 性能: 插入、删除和查找操作的时间复杂度为O(log(n))。
  • 特点:

    1. 唯一性和排序: Map集合中唯一性和排序都是针对键来说的。键是唯一的,而值可以发生重复。
    2. 键的唯一性: 在Map集合中,每个键只能映射到一个值,不能有重复的键。
    3. 值的重复性: 一个值可以对应多个键,即值可以重复。

示例代码

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

public class MapExample {
    public static void main(String[] args) {
         // HashMap 示例
         Map<String, Integer> hashMap = new HashMap<>();
         hashMap.put("Apple", 1);
         hashMap.put("Banana", 2);
         System.out.println(hashMap.get("Apple")); // 输出: 1

         // TreeMap 示例
         Map<String, Integer> treeMap = new TreeMap<>();
         treeMap.put("Orange", 3);
         treeMap.put("Mango", 4);
         System.out.println(treeMap); // 输出: {Mango=4, Orange=3},已排序
     }
}

总结

  • Map 接口存储键值对,键是唯一的,而值可以重复。
  • HashMap 提供了基于哈希表的快速键值对存储,但不保证元素的顺序。
  • TreeMap 通过红黑树实现,可以对键进行排序,适用于需要有序键集合的场景。
  • 选择合适的Map实现取决于具体需求,如是否需要排序、是否需要线程安全等。

Java 增强for循环,泛型和可变参数详细笔记

增强for循环

  • 使用场景:
    - 只能用于数组和实现了Collection接口的集合类型(如List, Set等)。
  • 语法:
    java for(元素类型 变量名 : 数组名|Collection集合名){ 使用变量名; }

静态导入

  • 语法:
    java import static <引用数据类型>.*;
  • 用途:
    - 允许直接使用静态成员(如静态方法和静态变量)而不需要类名作为前缀。

泛型

  • 泛型类:
    - 允许在类声明时定义类型参数,使得类的实例化可以接受不同的数据类型。
  • 泛型方法:
    - 在方法声明时定义类型参数,使得方法可以处理不同的数据类型,而与类的类型参数无关。
  • 泛型接口:
    - 定义时可以包含类型参数,使得实现该接口的类可以指定类型参数。

高级使用

  • 通配符:
    - <? extends E>: 表示类型参数是EE的子类。
    - <? super E>: 表示类型参数是EE的父类。
  • 用途:
    - 提供了更灵活的泛型使用方式,尤其是在处理继承关系中的类型时。

可变参数

  • 语法:
    java xxxXxx(数据类型...参数名)
  • 特点:
    - 可变参数允许在调用方法时传入任意数量的参数(包括零个)。
  • 注意事项:
    - 定义方法参数时,可变参数必须放在参数列表的最后。
    - 可变参数在方法内部被当作数组处理。

示例代码

import java.util.ArrayList;
import java.util.List;

public class GenericAndVarargsExample {
    // 泛型方法示例
     public static <T> void printList(List<T> list) {
         for (T element : list) {
             System.out.println(element);
         }
     }

     // 可变参数示例
     public static void printNumbers(int... numbers) {
         for (int number : numbers) {
             System.out.print(number + " ");
         }
     }

     public static void main(String[] args) {
         List<String> stringList = new ArrayList<>();
         stringList.add("Hello");
         stringList.add("World");
         printList(stringList); // 输出: Hello World

         printNumbers(1, 2, 3, 4, 5); // 输出: 1 2 3 4 5
     }
}

总结

  • 增强for循环 提供了一种简洁的方式来遍历数组和集合,但仅限于这些类型。
  • 静态导入 允许直接使用静态成员,简化代码,但需谨慎使用以避免命名冲突。
  • 泛型 提供了编译时类型安全检查和消除类型转换的功能,是处理集合和算法时的强大工具。
  • 通配符 在泛型中用于更灵活地处理类型关系,尤其是在方法参数中。
  • 可变参数 允许方法接受不定数量的参数,极大地提高了方法的灵活性和易用性。

Java Collections工具类笔记

Collections【工具类】

  • 概述:
    - Collections是Java提供的一个工具类,它包含了一系列静态方法,用于对集合进行操作,如排序、搜索、反转等。

  • 成员方法:
    - sort(List list):
    - 对指定的列表进行排序。
    - binarySearch(List list, T key)**: - 使用二分搜索算法搜索指定列表,以获得指定对象。 - **max(Collection coll):
    - 返回给定集合中的最大元素。
    - reverse(List list)**: - 反转指定列表中元素的顺序。 - **shuffle(List list):
    - 使用默认的随机源随机排列指定的列表。

将不安全的集合变成安全的

  • synchronizedCollection(Collection c):
    - 返回由指定集合支持的同步(线程安全)集合。
  • synchronizedList(List list):
    - 返回由指定列表支持的同步(线程安全)列表。
  • synchronizedMap(Map<K,V> m):
    - 返回由指定地图支持的同步(线程安全)映射。
  • synchronizedSet(Set s):
    - 返回由指定集合支持的同步(线程安全)集。

示例代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsExample {
    public static void main(String[] args) {
         List<Integer> list = new ArrayList<>();
         list.add(3);
         list.add(1);
         list.add(2);

          // 排序
          Collections.sort(list);
          System.out.println(list); // 输出: [1, 2, 3]

          // 反转
          Collections.reverse(list);
          System.out.println(list); // 输出: [3, 2, 1]

          // 二分搜索
          int index = Collections.binarySearch(list, 2);
          System.out.println("Index of 2: " + index); // 输出: Index of 2: 1

          // 同步集合
          List<Integer> syncList = Collections.synchronizedList(list);
          // 注意:同步集合是线程安全的,但迭代器不是
          // 如果需要迭代器,使用迭代器的synchronizedList方法
     }
}

总结

  • Collections 类提供了许多静态方法,用于对集合进行操作,如排序、搜索、反转等,极大地简化了集合操作。
  • 通过Collections类提供的同步方法,可以将普通的集合转换为线程安全的集合,适用于多线程环境。
  • 使用Collections类中的方法时,需要注意线程安全问题,特别是在迭代集合时。