当前位置: 首页 > news >正文

5java集合框架

 集合框架

Java 集合框架是 Java 提供的一组用于存储和操作数据的类和接口,它提供了高效、灵活且安全的数据存储和处理方式。

1. 集合框架的架构

Java 集合框架主要由两大接口派生而出:Collection 和 Map

  • Collection 接口:存储一组对象,它有三个主要的子接口:ListSet 和 Queue
  • Map 接口:存储键值对,键是唯一的,每个键对应一个值。
  • 其继承关系如下

     
    Collection
    ├── List(有序,允许重复)
    │   ├── ArrayList
    │   ├── LinkedList
    │   └── Vector
    ├── Set(无序,元素唯一)
    │   ├── HashSet
    │   ├── LinkedHashSet
    │   └── TreeSet
    └── Queue(队列结构)├── LinkedList(可作队列)└── PriorityQueue(优先级队列)Map
    ├── HashMap
    ├── LinkedHashMap
    ├── TreeMap
    └── Hashtable(线程安全但过时)

2. Collection 接口及其子接口

2.1 List 接口

List 是有序的集合,允许存储重复的元素。常见的实现类有 ArrayListLinkedList 和 Vector

  • ArrayList:基于动态数组实现,支持随机访问,插入和删除操作效率较低。
import java.util.ArrayList;
import java.util.List;public class ArrayListExample {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("apple");list.add("banana");System.out.println(list.get(0)); // 输出: apple}
}
  • LinkedList:基于双向链表实现,插入和删除操作效率较高,随机访问效率较低。

import java.util.LinkedList;
import java.util.List;public class LinkedListExample {public static void main(String[] args) {List<String> list = new LinkedList<>();list.add("apple");list.add("banana");System.out.println(list.get(0)); // 输出: apple}
}
  • Vector:与 ArrayList 类似,但它是线程安全的,不过性能相对较低。(已逐渐被替代)
2.2 Set 接口

Set 是不允许存储重复元素的集合。常见的实现类有 HashSetTreeSet 和 LinkedHashSet

  • HashSet:基于哈希表实现,不保证元素的顺序。
import java.util.HashSet;
import java.util.Set;public class HashSetExample {public static void main(String[] args) {Set<String> set = new HashSet<>();set.add("apple");set.add("banana");System.out.println(set.contains("apple")); // 输出: true}
}

HashSet 集合的主要特性之一是不允许存储重复元素。判断元素是否重复,依赖于元素的 hashCode() 和 equals() 方法。

  • 原理:当向 HashSet 中添加元素时,首先会调用元素的 hashCode() 方法计算哈希码,根据哈希码确定元素在内部存储结构(哈希表)中的位置。如果该位置已经有其他元素,则会调用 equals() 方法来比较这两个元素是否相等。若相等,则认为是重复元素,不会添加到集合中。
  • 示例:以下是一个自定义类的示例,展示了正确重写 hashCode() 和 equals() 方法的重要性。
import java.util.HashSet;class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}// 重写 hashCode 方法@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}// 重写 equals 方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age && (name != null ? name.equals(person.name) : person.name == null);}public static void main(String[] args) {HashSet<Person> set = new HashSet<>();Person p1 = new Person("Alice", 20);Person p2 = new Person("Alice", 20);set.add(p1);set.add(p2);System.out.println(set.size()); // 输出 1,因为 p1 和 p2 被认为是重复元素}
}

2. 空元素的添加

HashSet 允许添加一个 null 元素。因为 null 的 hashCode() 始终为 0,且在 HashSet 中只会存在一个 null 元素。

import java.util.HashSet;public class NullElementInHashSet {public static void main(String[] args) {HashSet<String> set = new HashSet<>();set.add(null);set.add(null);System.out.println(set.size()); // 输出 1,因为只允许有一个 null 元素}
}

  • TreeSet:基于红黑树实现,元素会按照比较器(元素所属的类必须实现 java.lang.Comparable 接口,并实现 compareTo() 方法)进行排序。如果元素所属的类没有实现 Comparable 接口,可以使用定制排序。定制排序需要在创建 TreeSet 时传入一个 Comparator 对象,Comparator 接口定义了 compare() 方法,用于指定元素之间的比较规则。
import java.util.TreeSet;
import java.util.Set;public class TreeSetExample {public static void main(String[] args) {Set<String> set = new TreeSet<>();set.add("apple");set.add("banana");System.out.println(set.first()); // 输出: apple}
}
import java.util.Comparator;
import java.util.TreeSet;public class CustomSortingExample {public static void main(String[] args) {// 创建一个 Comparator 对象,按照字符串长度进行比较Comparator<String> lengthComparator = new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return Integer.compare(s1.length(), s2.length());}};// 使用定制的 Comparator 创建 TreeSetTreeSet<String> treeSet = new TreeSet<>(lengthComparator);treeSet.add("apple");treeSet.add("banana");treeSet.add("cherry");treeSet.add("date");// 遍历 TreeSet,元素会按照字符串长度从小到大排序for (String str : treeSet) {System.out.println(str);}}
}

  • LinkedHashSet:基于哈希表和链表实现,保证元素的插入顺序。
import java.util.LinkedHashSet;public class LinkedHashSetExample {public static void main(String[] args) {// 创建一个 LinkedHashSet 实例LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();// 添加元素到 LinkedHashSetlinkedHashSet.add("apple");linkedHashSet.add("banana");linkedHashSet.add("cherry");// 尝试添加重复元素,不会被添加linkedHashSet.add("apple");// 输出 LinkedHashSet 的元素,元素顺序与插入顺序一致System.out.println("LinkedHashSet 中的元素:");for (String element : linkedHashSet) {System.out.println(element);}// 检查元素是否存在boolean containsBanana = linkedHashSet.contains("banana");System.out.println("是否包含 banana: " + containsBanana);// 移除元素linkedHashSet.remove("cherry");System.out.println("移除 cherry 后,LinkedHashSet 中的元素:");for (String element : linkedHashSet) {System.out.println(element);}// 检查集合是否为空boolean isEmpty = linkedHashSet.isEmpty();System.out.println("LinkedHashSet 是否为空: " + isEmpty);// 获取集合的大小int size = linkedHashSet.size();System.out.println("LinkedHashSet 的大小: " + size);}
}    

2.3 Queue 接口

Queue 是队列接口,遵循先进先出(FIFO)原则。常见的实现类有 LinkedList(也实现了 Queue 接口)和 PriorityQueue

  • PriorityQueue:基于堆实现。
  • 元素按自然序或Comparator排序(使用场景:任务优先级处理、堆排序)
import java.util.PriorityQueue;
import java.util.Queue;public class PriorityQueueExample {public static void main(String[] args) {Queue<Integer> queue = new PriorityQueue<>();queue.add(3);queue.add(1);queue.add(2);System.out.println(queue.poll()); // 输出: 1}
}

3. Map 接口及其实现类

Map 存储键值对,键是唯一的。常见的实现类有 HashMapTreeMap 和 LinkedHashMap

  • HashMap:基于哈希表实现,不保证键值对的顺序。
import java.util.HashMap;
import java.util.Map;public class HashMapExample {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("apple", 1);map.put("banana", 2);System.out.println(map.get("apple")); // 输出: 1}
}

  • TreeMap:基于红黑树实现,键会按照自然顺序或指定的比较器进行排序。
import java.util.TreeMap;
import java.util.Map;public class TreeMapExample {public static void main(String[] args) {Map<String, Integer> map = new TreeMap<>();map.put("apple", 1);map.put("banana", 2);System.out.println(map.firstKey()); // 输出: apple}
}
  • LinkedHashMap:基于哈希表和链表实现,保证键值对的插入顺序。 是 Java 中 Map 接口的一个实现类,它继承自 HashMap,同时维护了一个双向链表,用来记录元素的插入顺序或者访问顺序
  • 当构造函数中设置 accessOrder=true 时,每次调用 get() 或 put() 方法访问元素时,该元素会被移动到双向链表的​​尾部​​(即最近访问的元素排在最后)
        LinkedHashMap<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);map.put("A", 1);map.put("B", 2);map.put("C", 3);遍历结果:A → B → Cfor (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());}
// 访问元素 "B"Integer b = map.get("B");System.out.println("============访问了B元素的值:"+b);// 遍历结果:A → C → B(B 被移动到末尾)for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());}
构建 LRU 缓存

通过重写 removeEldestEntry 方法,可自动淘汰最久未访问的元素

LinkedHashMap<Integer, String> lruCache = new LinkedHashMap<>(3, 0.75f, true) {@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {return size() > 3; // 容量超过3时移除最旧元素}
};lruCache.put(1, "One");
lruCache.put(2, "Two");
lruCache.put(3, "Three");
lruCache.get(1); // 访问元素1,使其保留
lruCache.put(4, "Four"); // 触发淘汰,移除元素2
System.out.println(lruCache); // 输出:{1=One, 3=Three, 4=Four}

LinkedHashMap 本身非线程安全,多线程环境下需通过 Collections.synchronizedMap() 或并发包(如 ConcurrentHashMap)实现同步

4. 集合的遍历

可以使用迭代器、for-each 循环或 Java 8 的 Stream API 来遍历集合。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class CollectionTraversal {public static void main(String[] args) {List<String> c = new ArrayList<>();c.add("apple");c.add("banana");// 使用迭代器遍历Iterator<String> iterator = c.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}// 使用 for-each 循环遍历for (String element : c) {System.out.println(element);}// 使用 Stream API 遍历c.stream().forEach(System.out::println);}
}

集合 forEach 遍历

5. 线程安全的集合

Java 提供了一些线程安全的集合类,如 VectorHashtable,以及 Collections.synchronizedXXX 方法返回的同步集合,还有 Java 并发包中的 ConcurrentHashMapCopyOnWriteArrayList 等。

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;public class ThreadSafeCollection {public static void main(String[] args) {// 使用 Collections.synchronizedMap 方法创建线程安全的 MapMap<String, Integer> map = new HashMap<>();Map<String, Integer> synchronizedMap = Collections.synchronizedMap(map);}
}

Java 集合框架提供了丰富的类和接口,以满足不同的需求。在实际开发中,需要根据具体的场景选择合适的集合类。

Stream流

1. Stream 是 Java 8 引入的一个新的抽象概念,

它代表了一个来自数据源的元素序列,支持聚合操作。数据源可以是集合、数组、I/O 通道等。Stream 操作分为中间操作和终端操作。

2. Stream 流的创建

2.1 从集合创建

可以通过集合的 stream() 或 parallelStream() 方法创建 Stream 流。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;public class StreamCreationFromCollection {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("apple");list.add("banana");list.add("cherry");// 创建顺序流Stream<String> sequentialStream = list.stream();// 创建并行流Stream<String> parallelStream = list.parallelStream();}
}
2.2 从数组创建

使用 Arrays.stream() 方法从数组创建 Stream 流。

import java.util.Arrays;
import java.util.stream.Stream;public class StreamCreationFromArray {public static void main(String[] args) {String[] array = {"apple", "banana", "cherry"};Stream<String> stream = Arrays.stream(array);}
}
2.3 使用 Stream.of() 方法

可以直接使用 Stream.of() 方法创建 Stream 流。

import java.util.stream.Stream;public class StreamCreationUsingOf {public static void main(String[] args) {Stream<String> stream = Stream.of("apple", "banana", "cherry");}
}

3. 中间操作

中间操作会返回一个新的 Stream,允许进行链式调用。常见的中间操作有:

3.1 filter()

用于过滤满足条件的元素。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class FilterExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());System.out.println(evenNumbers);}
}
3.2 map()

用于对元素进行转换。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class MapExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3);List<Integer> squaredNumbers = numbers.stream().map(n -> n * n).collect(Collectors.toList());System.out.println(squaredNumbers);}
}
3.3 sorted()

用于对元素进行排序。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class SortedExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(3, 1, 2);List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList());System.out.println(sortedNumbers);}
}
3.4 distinct()

用于去除重复元素。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class DistinctExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());System.out.println(distinctNumbers);}
}

4. 终端操作

终端操作会触发 Stream 流的处理,并产生一个结果或副作用。常见的终端操作有:

4.1 forEach()

用于对每个元素执行操作。

import java.util.Arrays;
import java.util.List;public class ForEachExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3);numbers.stream().forEach(n -> System.out.println(n));}
}
4.2 collect()

用于将 Stream 流中的元素收集到一个集合中。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class CollectExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3);List<Integer> squaredNumbers = numbers.stream().map(n -> n * n).collect(Collectors.toList());System.out.println(squaredNumbers);}
}
4.3 reduce()

用于将 Stream 流中的元素进行合并。

import java.util.Arrays;
import java.util.List;
import java.util.Optional;public class ReduceExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3);Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);sum.ifPresent(System.out::println);}
}
4.4 count()

用于统计 Stream 流中元素的数量。

import java.util.Arrays;
import java.util.List;public class CountExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3);long count = numbers.stream().count();System.out.println(count);}
}

5. 并行流

并行流可以利用多核处理器的优势,并行处理 Stream 流中的元素,提高处理性能。但需要注意线程安全问题。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class ParallelStreamExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);List<Integer> squaredNumbers = numbers.parallelStream().map(n -> n * n).collect(Collectors.toList());System.out.println(squaredNumbers);}
}

相关文章:

  • 虚幻引擎5-Unreal Engine笔记之UE编辑器退出时的保存弹框
  • Level1.5算数运算符与赋值运算符
  • 时钟晶振锁相环pll方向技术要点和大厂题目解析
  • nvme Unable to change power state from D3cold to D0, device inaccessible
  • DS18B20温度传感器
  • [思维模式-25]:《本质思考力》-6- 马克思主义哲学的五对基本哲学范畴,以及在计算机领域的体现
  • Linux系统之----模拟实现shell
  • 技嘉主板BIOS升级
  • 单片机-STM32部分:10-2、逻辑分析仪
  • Android开发-Activity启停
  • JAVA练习题(2) 找素数
  • 【Bootstrap V4系列】学习入门教程之 组件-输入组(Input group)
  • (2025)图文解锁RAG从原理到代码实操,代码保证可运行
  • 【基于 LangChain 的异步天气查询2】GeoNames实现地区实时气温查询
  • 棒球裁判员学习指南·棒球1号位
  • dify插件接入fastmcp示例
  • Satori:元动作 + 内建搜索机制,让大模型实现超级推理能力
  • 一文理解扩散模型(生成式AI模型)(1)
  • 初等数论--莫比乌斯函数
  • OSPF综合应用
  • 美凯龙:董事兼总经理车建兴被立案调查并留置
  • 视频丨美国两名男童持枪与警察对峙,一人还试图扣动扳机
  • 事关心脏健康安全,经导管植入式人工心脏瓣膜国家标准发布
  • 国产水陆两栖大飞机AG600批产首架机完成总装下线
  • 江西省司法厅厅长张强已任江西省委政法委分管日常工作副书记
  • 王毅同印度国家安全顾问多瓦尔通电话