首页 > 编程语言 >在 Java 中使用集合框架

在 Java 中使用集合框架

时间:2023-03-19 14:01:37浏览次数:41  
标签:Java 框架 实现 元素 接口 线程 集合 排序

一. 什么是集合框架

集合框架的概述

Java中的集合框架是一组用于管理和操作对象集合的类和接口,它们提供了比数组更高级别的数据结构和算法,以及更方便的数据访问和操作方式。

Java集合框架包括两种类型的集合:一种是基于接口的集合,另一种是基于类的集合。其中基于接口的集合是定义集合操作的一组接口,包括List、Set、Queue、Deque、Map等。基于类的集合是实现这些接口并提供特定实现的类,例如ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等。

集合框架的类库结构

  1. Collection接口:是所有集合接口的父接口,定义了集合的基本操作方法,包括添加、删除、遍历等。
  2. List接口:是Collection接口的子接口,表示一个有序的元素集合,允许元素重复。
    a. ArrayList类:是List接口的一个实现类,使用数组实现,支持快速随机访问。
    b. LinkedList类:也是List接口的一个实现类,使用双向链表实现,支持高效的插入和删除操作。
  3. Set接口:同样是Collection接口的子接口,表示一个不包含重复元素的无序集合。
    a. HashSet类:是Set接口的一个实现类,使用哈希表实现,插入和查询效率高,不保证元素顺序。
    b. TreeSet类:也是Set接口的一个实现类,使用红黑树实现,能够按照元素的自然顺序或指定的比较器进行排序。
  4. Queue接口:表示一个先进先出(FIFO)的元素集合。
    a. LinkedList类:是Queue接口的一个实现类,也可以用作Stack(栈)数据结构。
    b. PriorityQueue类:也是Queue接口的一个实现类,实现了优先级队列,元素按照自然顺序或指定的比较器进行排序。
  5. Deque接口:是Queue接口的子接口,表示一个双端队列,可以在队列的两端添加或删除元素。
    a. LinkedList类:也是Deque接口的一个实现类,可以同时作为队列和栈使用。
    b. ArrayDeque类:也是Deque接口的一个实现类,使用循环数组实现,可以作为栈、队列或双端队列使用。
  6. Map接口:表示一组键值对的映射,每个键只能对应一个值。
    a. HashMap类:是Map接口的一个实现类,使用哈希表实现,插入和查询效率高,不保证元素顺序。
    b. TreeMap类:也是Map接口的一个实现类,使用红黑树实现,能够按照键的自然顺序或指定的比较器进行排序。

除了这些核心接口和类之外,Java集合框架还提供了一些辅助类和接口,如Collections、Comparator、Iterator、Enumeration等,它们都提供了在集合操作中非常有用的方法和功能。

二. 集合框架中的基本接口和类

Collection接口和常用实现类(List、Set)

Collection接口是Java集合框架的根接口,它定义了一组通用的集合操作方法,包括添加、删除、遍历、判断是否包含等。常用的实现类包括List和Set。

List接口表示一个有序的元素集合,允许元素重复。常用的实现类有:

  1. ArrayList类:使用数组实现,支持快速随机访问,适合于随机访问,但是不适合于在中间位置插入或删除元素。
  2. LinkedList类:使用双向链表实现,支持高效的插入和删除操作,适合于在中间位置插入或删除元素,但是访问元素的效率较低。

Set接口表示一个不包含重复元素的无序集合。常用的实现类有:

  1. HashSet类:使用哈希表实现,插入和查询效率高,不保证元素顺序。
  2. TreeSet类:使用红黑树实现,能够按照元素的自然顺序或指定的比较器进行排序。

下面是一个示例代码,演示了如何使用ArrayList和HashSet类:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CollectionExample {
public static void main(String[] args) {
// 使用ArrayList存储整数
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(2); // 允许元素重复
System.out.println("ArrayList: " + list);

// 使用HashSet存储字符串
Set<String> set = new HashSet<>();
set.add("apple");
set.add("orange");
set.add("banana");
set.add("orange"); // 不允许元素重复
System.out.println("HashSet: " + set);
}
}

Map接口和常用实现类

Map接口表示一组键值对的映射关系,每个键最多只能映射到一个值。常用的实现类有:

  1. HashMap类:使用哈希表实现,插入和查询效率高,不保证元素顺序。
  2. TreeMap类:使用红黑树实现,能够按照键的自然顺序或指定的比较器进行排序。
  3. LinkedHashMap类:使用哈希表和双向链表实现,保证元素按照插入顺序排序。

下面是一个示例代码,演示了如何使用HashMap和TreeMap类:

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

public class MapExample {
public static void main(String[] args) {
// 使用HashMap存储成绩
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 90);
map.put("Bob", 85);
map.put("Charlie", 92);
map.put("Bob", 88); // 相同的键会覆盖原有的值
System.out.println("HashMap: " + map);

// 使用TreeMap存储成绩
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Alice", 90);
treeMap.put("Bob", 85);
treeMap.put("Charlie", 92);
treeMap.put("Bob", 88); // 相同的键会覆盖原有的值
System.out.println("TreeMap: " + treeMap);
}
}

三. 集合框架中的算法

排序算法

集合框架中提供了多种排序算法,其中Arrays类和Collections类提供了一些静态方法来对数组或集合进行排序。

  1. Arrays.sort()方法:对数组进行排序,使用快速排序或归并排序算法,时间复杂度为O(nlogn)。
  2. Arrays.parallelSort()方法:对数组进行并行排序,多线程执行排序算法,可以提高排序的速度。
  3. Collections.sort()方法:对集合进行排序,使用归并排序算法,时间复杂度为O(nlogn)。
  4. Collections.reverse()方法:对集合进行反转操作。

下面是一个示例代码,演示了如何使用Arrays类和Collections类进行排序操作:

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

public class SortExample {
public static void main(String[] args) {
// 对数组进行排序
int[] arr = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
Arrays.sort(arr);
System.out.println("Sorted Array: " + Arrays.toString(arr));

// 对集合进行排序
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5));
Collections.sort(list);
System.out.println("Sorted List: " + list);

// 对集合进行反转操作
Collections.reverse(list);
System.out.println("Reversed List: " + list);
}
}

需要注意的是,在使用sort()方法进行排序时,集合中的元素必须实现Comparable接口或传入比较器Comparator对象,否则会抛出ClassCastException异常。

查找算法

集合框架中提供了两种查找算法,分别是线性查找和二分查找。

  1. 线性查找:逐一比较集合中的元素,直到找到指定的元素或搜索到集合的末尾。
  2. 二分查找:对于有序集合,可以使用二分查找算法进行查找。首先将集合按照元素大小排序,然后在集合的中间位置开始查找,如果中间元素等于指定元素,则查找成功;否则,如果指定元素小于中间元素,则在左半部分集合中查找;否则,在右半部分集合中查找。重复以上步骤,直到找到指定元素或者集合被搜索完毕。

下面是一个示例代码,演示了如何使用线性查找和二分查找算法:

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

public class SearchExample {
public static void main(String[] args) {
// 线性查找
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5));
int index = list.indexOf(9);
System.out.println("Index of 9: " + index);

// 二分查找
Collections.sort(list);
int index2 = Collections.binarySearch(list, 9);
System.out.println("Index of 9: " + index2);
}
}

需要注意的是,在使用二分查找算法进行查找时,集合必须是有序的,否则可能得到错误的结果。另外,在使用binarySearch()方法进行查找时,如果查找的元素不存在于集合中,会返回一个负数,表示应该插入该元素的位置。


四. 集合框架中的线程安全问题

非线程安全的集合类

在Java集合框架中,有些类是非线程安全的,这意味着它们不适用于多线程环境,如果多个线程同时访问这些集合类的实例,可能会导致不可预测的结果。以下是一些非线程安全的集合类:

  1. ArrayList:它是一个基于数组实现的动态数组,可以在任意位置插入或删除元素。在多线程环境下,如果同时对ArrayList进行修改操作,可能会导致数据不一致或者抛出ConcurrentModificationException异常。
  2. LinkedList:它是一个基于链表实现的双向链表,可以在任意位置插入或删除元素。在多线程环境下,如果同时对LinkedList进行修改操作,可能会导致数据不一致或者抛出ConcurrentModificationException异常。
  3. HashMap:它是一个基于哈希表实现的键值对映射,可以快速查找指定的元素。在多线程环境下,如果同时对HashMap进行修改操作,可能会导致数据不一致或者抛出ConcurrentModificationException异常。
  4. HashSet:它是一个基于哈希表实现的集合,可以快速查找指定的元素。在多线程环境下,如果同时对HashSet进行修改操作,可能会导致数据不一致或者抛出ConcurrentModificationException异常。

如果需要在多线程环境中使用集合类,可以考虑使用线程安全的集合类,例如Vector、Hashtable、ConcurrentHashMap、CopyOnWriteArrayList和CopyOnWriteArraySet等。另外,也可以使用synchronized关键字或Lock对象来保证多线程安全。

线程安全的集合类

在Java集合框架中,线程安全的集合类是为多线程环境设计的,可以保证在多个线程同时访问时,不会出现数据不一致或者抛出ConcurrentModificationException异常等线程安全问题。以下是一些常用的线程安全的集合类:

  1. Vector:它是一个基于数组实现的动态数组,与ArrayList类似,但是所有的方法都是同步的,因此在多线程环境中可以保证线程安全。
  2. Hashtable:它是一个基于哈希表实现的键值对映射,与HashMap类似,但是所有的方法都是同步的,因此在多线程环境中可以保证线程安全。
  3. ConcurrentHashMap:它是一个基于哈希表实现的键值对映射,与HashMap类似,但是在多线程环境中使用更加高效。ConcurrentHashMap使用了分段锁的机制,将整个哈希表分成若干个段,每个段独立加锁,因此不同的线程可以同时访问不同的段,从而提高了并发性能。
  4. CopyOnWriteArrayList:它是一个基于数组实现的动态数组,与ArrayList类似,但是在修改操作时会创建一个新的数组,因此可以保证并发修改时的线程安全。适用于读多写少的场景。
  5. CopyOnWriteArraySet:它是一个基于CopyOnWriteArrayList实现的集合,与HashSet类似,但是可以保证并发修改时的线程安全。

需要注意的是,线程安全的集合类在多线程环境下虽然可以保证线程安全,但是会带来额外的开销,因此在单线程环境下使用可能会影响性能。因此,在选择集合类时需要根据实际需求来选择合适的集合类。




标签:Java,框架,实现,元素,接口,线程,集合,排序
From: https://blog.51cto.com/jiangdy/6131198

相关文章

  • 【Android 逆向】【攻防世界】easyjava
    1.apk安装到手机,提示输入flag2.jadx打开apk看看privatestaticchara(Stringstr,bbVar,aaVar){returnaVar.a(bVar.a(str));}/*JAD......
  • flask框架,查询某个目录下文件列表,目录列表,查询是否存在某个文件
    #要查询的目录directory='/path/to/directory'#获取目录下的所有文件和目录contents=os.listdir(directory)#筛选出所有的文件files=[......
  • 【JavaScript】49_DOM编程:DOM修改与demo
    10、DOM的修改appendChild()用于给一个节点添加子节点list.appendChild(li)insertAdjacentElement()可以向元素的任意位置添加元素两个参数:1.要添加的位置2.要添加的元素be......
  • Java中“==”与equals()
    1前言1.1内存分区Java中有6种存储区域(参考Java的六大存储区域),如下:寄存器(register):位于处理器内部,处理速度最快,空间比较珍贵;栈(stack):位于通用RAM中,处理速度仅次于寄存......
  • Java容器及其常用方法汇总
    1概述JavaCollections框架中包含了大量的接口及其实现类和操作它们的算法,主要包括列表(List)、集合(Set)、映射(Map),如下:接口实现类数据结构初始容量加载因子扩容......
  • Java线程池详解
    1使用线程池的好处降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗;提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行;提高线程的......
  • 【MyBatis框架】mybatis和spring整合
    spring和mybatis整合1.整合思路需要spring通过单例方式管理SqlSessionFactory。spring和mybatis整合生成代理对象,使用SqlSessionFactory创建Sql......
  • 【MyBatis框架】查询缓存-一级缓存原理
    查询缓存1.什么是查询缓存mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits提供一级缓存,和二级缓存。缓存模式图如图一级缓存是......
  • 【MyBatis框架】高级映射-多对多查询
    多对多查询1.需求查询用户及用户购买商品信息。2.sql语句查询主表是:用户表关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所......
  • 【Android开发】用户界面设计-使用XML和Java代码混合控制UI界面
    效果图:res/layout/main.xml:<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:......