当前位置: 首页 > 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);}
}

http://www.xdnf.cn/news/388783.html

相关文章:

  • # Ollama 实现大模型调用
  • 无侵入式弹窗体验_探索 Chrome 的 Close Watcher API
  • Android Canvas API 详细说明与示例
  • python【扩展库】websockets
  • idea中的vcs不见了,如何解决
  • 探秘 DeerFlow:字节跳动开源的科研创作魔法盒!
  • 温湿度传感器SHT4X
  • 【C++】AVL树实现
  • 害怕和别人发生冲突怎么办? --deepseek
  • [特殊字符] 免税商品优选购物商城系统 | Java + SpringBoot + Vue | 前后端分离实战项目分享
  • 线程的一些事(2)
  • 拍摄学习笔记【前期】(一)曝光
  • SQL 数据库监控:SQL语句监控工具与实践案例
  • 【Redis】Redis的主从复制
  • Linux常见指令解析(三)
  • jenkins built-in节点如何删除
  • TeledyneLeCroy在OFC2025 EA展台上展示了其400G/800G的全包围的测试解决方案,满足了UEC联盟和UALINK联盟的技术需求
  • 【25软考网工】第六章(3)数字签名和数字证书
  • opencv关键点检测
  • C语音学习---函数指针
  • Redis爆肝总结
  • 【嵌入式DIY实例-Arduino篇】-DIY遥控手柄
  • IC ATE集成电路测试学习——电流测试的原理和方法
  • 数据库与SQL核心技术解析:从基础到JDBC编程实战
  • 设计模式系列(1):总览与引导
  • NX989NY104美光科技芯片NY109NY113
  • LVGL(lv_btnmatrix矩阵按钮)
  • Babel 基础使用指南:从安装到编译的完整流程
  • MySQL主从复制
  • CacheBackEmbedding 组件的运行流程和使用注意事项