Java 数组和集合

本文介绍了Java基本类型,包括基本数据类型和引用数据类型及缓存情况。阐述了Java数组的创建、数组与集合的转换及注意问题。还详细讲解了Java集合,如List、Set、Map的实现类特点,以及Collections集合工具类对集合元素的排序、搜索等操作。

〇、Java 基本类型。

今天一个同学问我,Java 基本类型 int 类型是 4 个字节 ? char 呢 ?

Java 有两大基本类型:基本数据类型和引用数据类型

  • 基本数据类型(8 种,四整两浮一符一布):默认的整型是 int ,默认的浮点型是 double。
    对于数值类型的基本类型的取值范围,我们无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了。
    在这里插入图片描述
    在这里插入图片描述
  • 引用数据类型(除去上述基本类型的包装类以外,还有由类的构造函数创建,可以使用它们访问所引用的对象。):对象、数组都是引用数据类型,引用数据类型的默认值都是 null 。

需要注意缓存。

  • Boolean(全部缓存)
  • Byte(全部缓存)
  • Integer(-128 — 127 缓存)
  • Short(-128 — 127 缓存)
  • Long(-128 — 127 缓存)
  • Character(<= 127缓存)
  • Float(没有缓存)
  • Doulbe(没有缓存)

一、Java 数组

Java 语言中提供的数组是用来存储固定大小的同类型元素。
Java语言使用new操作符来创建数组,语法如下:(详细内容请查看菜鸟教程

arrayRefVar = new dataType[arraySize];
上面语句做了两件事:1、使用 dataType[arraySize] 创建了一个数组。
          2、把新创建的数组的引用赋值给变量 arrayRefVar。

  1. 创建和声明同时 :dataType[] arrayRefVar = new dataType[arraySize];
  2. 声明时,直接填充内容:dataType[] arrayRefVar = {value0, value1, ..., valuek};

数组转集合( Arrays.asList(array) ),集合转数组( list.toArray() )。

  1. 数组转集合使用 Arrays 的 asList 方法,它将数组转化成一个List,可以用这个 List 构造Set。Set set = new HashSet(Arrays.asList(array));
  2. 集合转数组使用 toArray 方法,可以通过强转来得到目标数组。
    array2 = (String[]) set.toArray(new String[set.size()]); ( 将 list 中的内容放入参数数组中,当参数数组的长度小于 list 的元素个数时,会自动扩充数组的长度以适应 list 的长度,这条语句直接使用了集合的长度 )

需要注意的问题。

  1. asList() 原始类型不能作为 Arrays.asList 方法的参数,否则会被当做一个参数。
    查看源码:T 作为泛型的参数,而基本类型是不能够作为泛型参数的。
int[] list = {1,2,3,4};
List list = Arrays.asList(list);
System.out.println(list.size()); 	 // 编辑器把 int[] 数组当做了一个引用的参数对象,输出值 1
  1. Arrays.asList(list) 返回的 ArrayList 是 Arrays 的静态内部私有类实现,继承了 AbstractList ,属于不可变结构,不是常用的那个 ArrayList ,只实现了size 、toArray、get、set、contains几个方法,具体请看源码【Ctrl + 点击方法名】。
    下图中,不可变结构的 Arrays 的 ArrayList 通过构造放入真正的 ArrayList,就可以正常使用了。
    在这里插入图片描述
    在这里插入图片描述
  2. 集合的相等只在乎元素数据的比较,其中 equals 方法都是 AbstractList 中实现的,比较的依据是通过迭代器遍历元素挨个 equals 比较。
    在这里插入图片描述

二、Java 集合

集合按照存储结构可以分为,单列集合 Collection 和 双列集合 Map 。

  1. Collection :单列集合类的根接口,用于存储一系列符合某种规则的元素。重要的两个子类 List 和 Set 。List 是有序可重复,接口主要实现类 ArrayList 和 LinkedList 。Set 是无序不能重复,接口主要实现类有 HashSet 和 TreeSet 。
  2. Map :双列集合类的根接口,用于存储具有键值(Key-Value)映射关系的元素。可以通过指定的 Key 找到对应的 Value 。Map 的主要实现类有 HashMap 和 TreeMap 。

在这里插入图片描述

①、List 是有序可重复,接口主要实现类 ArrayList 和 LinkedList

ArrayList 集合

  1. Array 与 ArrayList 的区别。
    ①、Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类型。
    ②、Array 的大小是固定的,ArrayList 的大小是动态变化的,ArrayList 提供了更多的方法和特性,addAll()、removeAll()、iterator() 等方法。

LinkedList 集合

集合内部维护了一个双向循环链表,链表元素都使用引用的方式来记住它的前一个元素和后一个元素,从而将所有元素连接起来。

  1. 最基本的使用。
    在这里插入图片描述
ArrayList 和 LinkedList 的区别。

主要区别:

  1. ArrayList 是实现了基于动态数组的数据结构,ArrayList 集合在查询元素的时候速度很快,但在增删元素时效率较低。因为 LinkedList 要移动指针。
  2. LinkedList 基于链表的数据结构,对于新增和删除操作 add 和 remove,LinedList 比较占优势,因为 ArrayList 要移动数据,而 linkedList 只需要改变引用的前后关系。

Iterator 接口(迭代器)

Iterator 主要用于迭代访问(即遍历)Collection 中的元素。

  1. Collection 集合遍历
    在这里插入图片描述
  2. Map 集合遍历
    在这里插入图片描述

②、Set 是无序不能重复,接口主要实现类有 HashSet 和 TreeSet

HashSet 集合

为保证 HashSet 正常操作,要求在存入对象时,重写 Object 类中的 hashCode() 和 equals() 方法。

  1. add("Json") ,会先调用对象的 hashCode() 方法获取哈希值,通过哈希值确定存储地址,地址没对象直接存入,地址有对象则进行 equals() 方法进行判断,相等则舍弃,不等则覆盖。在使用自定义对象的时候,一定要注意重写 hashCode() 与 equals() .
    在这里插入图片描述

TreeSet 集合

③、Map 的实现类有 HashTable、HashMap 和 TreeMap

HashTable 集合

HashMap 集合

  1. 遍历集合的两种方式。
// 第一种:先遍历 Map 集合中的所有键,再根据键获取相应的值
Set keys = map.keySet(); 		// 获取键的集合
Iterator it = keys.iterators();		// 迭代键值
it.hasNext();		// 判断下一个元素是否有内容
it.next();		// 获取值
map.get(key);		// 通过 key  获取 values 。
// 第二种:通过 values() 方法直接获取 Map 集合的所有值的 Collection 集合。
Collection values = map.values();	// 获取 map 存储的所有值。

TreeMap 集合

  1. TreeMap 的红黑树。

红黑树就是节点是红色或者黑色的平衡二叉树,它通过颜色的约束来维持着二叉树的平衡。对于一棵有效的红黑树二叉树而言我们必须增加如下规则:
1、每个节点都只能是红色或者黑色
2、根节点是黑色
3、每个叶节点(NIL节点,空节点)是黑色的。
4、如果一个结点是红的,则它两个子节点都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。
5、从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

Properties 集合

  1. Java 读取 Properties 文件(注意文件路径)。
    在这里插入图片描述

叁、Collections 集合工具类。

Collections 则是集合类的一个工具类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

  1. 对集合进行排序。Collections.sort(Collection);
    在这里插入图片描述
  2. 进行随机排序。Collections.shuffle(Collection);
    在这里插入图片描述
  3. 返回所查找元素的索引。Collections.binarySearch(Collection,Object);

这里我采用了两种情况进行测试,已知存在和不存在的部分,但是出现如图所示的问题,查找存在和不存在的字符串都是 负数(表示不存在的意思。)
在这里插入图片描述
原因:Collections 的 binarySearch 方法的查找功能,但是要是用二分查找的 List 必须是有序的,也就是使用 Collections 中的 sort 方法进行自然排序。
在这里插入图片描述
补充内容:-1 不是判断不存在的唯一标准,Java 编程技巧 2019.05.19 第5条

  1. 替换批定元素为某元素,若要替换的值存在刚返回true,反之返回false。Collections.replaceAll(List list,Object old,Object new);
  2. 反转集合中元素的顺序。Collections.reverse() ;
    在这里插入图片描述
  3. 集合中的元素向后移m个位置,在后面被遮盖的元素循环到前面来。Collections.rotate(List list,int m)
    在这里插入图片描述
    在这里插入图片描述
  4. 集合 n 中的元素全部复制到 m 中,并且覆盖相应索引的元素。Collections.copy(List m,List n);
  5. 交换集合中指定元素索引的位置。Collections.swap(List list,int i,int j);
    在这里插入图片描述
  6. 用对象 o 替换集合 list 中的所有元素Collections.fill(List list,Object o);
  7. 返回大小为 n 的 List,List 不可改变,其中的所有引用都指向 o。Collections.nCopies(int n,Object o);
  8. 返回集合中的最大最小值。max();、min();
    在这里插入图片描述
<think>首先,用户的问题是:“我想了解Java数组集合的区别 请问Java数组集合的区别”,这明确要求我解释Java数组集合的区别。 我有系统级指令: - 所有行内数学表达式使用$...$格式(但这里可能不涉及数学表达式)。 - 独立公式使用$$...$$格式(同样,可能不适用)。 - LaTeX语法正确(主要是数学相关,但需注意)。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户提供了四个引用: - 引用[1]: 讨论Java数组集合的区别,包括存储方式、长度固定性等。 - 引用[2]: 详细比较数组集合的特性,如长度、存储类型类型安全、内存分配、功能方法等。 - 引用[3]: 强调长度、数据类型等区别。 - 引用[4]: 提到集合类如ListMap。 我需要基于这些引用来回答,但要参考用户上一次的问题我的回答。用户上一次的问题是相同的:“我想了解Java数组集合的区别”,所以没有历史对话变化。我必须使用提供的引用来构建回答。 回答结构: - 结构清晰,帮助用户逐步解决问题。 - 保证真实可靠(基于引用)。 - 最后生成相关问题。 关键区别点(基于引用): 1. **长度(固定 vs 动态)**:数组长度固定,创建时指定;集合长度动态可变(例如ArrayList可通过扩容调整)。 2. **存储类型**:数组可以存储基本数据类型(如int, char)对象;集合只能存储对象引用(基本类型需用包装类如Integer)。 3. **类型安全**:数组在编译时不检查元素类型集合使用泛型(Generics)保证类型安全(如List<String>)。 4. **内存分配访问**:数组是连续内存空间,索引访问O(1);集合如LinkedList可能需O(n)遍历。 5. **功能方法**:数组支持基础操作(索引访问),复杂操作需Arrays工具类;集合提供丰富方法(add, remove, sort等)。 6. **元素唯一性**:数组允许重复;集合如Set强制唯一性,List允许重复。 7. **转换**:数组集合可相互转换(如Arrays.asList(), list.toArray())。 组织回答: 1. **引言**:简要介绍数组集合是什么。 2. **主要区别**:列出关键点,逐步解释。 3. **源代码示例**:引用中提到给出源代码示例,我应该包括一些简单的Java代码来演示。 4. **总结**:简要概括。 5. **相关问题**:生成几个相关问题。 使用中文回答。 引用标识:在回答中,当引用具体内容时,在末尾添加[^n],例如基于引用[2]的内容添加[^2]。 生成相关问题:类似于示例,最后添加“相关问题”部分。 大纲: 1. **开头**:解释Java数组集合基本概念。 2. **区别列表**: - 长度 - 存储类型 - 类型安全 - 内存访问效率 - 功能方法 - 元素唯一性 - 转换方式 3. **代码示例**:例如,创建一个数组一个ArrayList,展示添加元素等操作。 4. **总结**:何时使用数组,何时使用集合。 5. **相关问题**:生成2-3个相关问题。 相关问题想法: - Java中如何将数组转换为集合? - 哪些场景更适合使用数组而不是集合? - 集合框架中的主要接口有哪些? </think>### Java数组集合的区别 Java中的数组集合都是用于存储多个元素的容器,但它们在设计、功能用法上有显著差异。以下是基于核心概念的关键区别点,我将逐步解释并结合简单源代码示例说明。这些差异主要体现在长度动态性、存储类型类型安全、性能功能方法上[^1][^2][^3]。 #### 1. **长度管理(固定 vs 动态)** - **数组**:长度在创建时固定,无法在运行时改变。例如,声明一个整数数组后,不能添加或删除元素。 ```java int[] arr = new int[3]; // 固定长度为3 arr[0] = 10; // 合法 // arr[3] = 20; // 错误:索引越界,数组长度无法扩展 ``` - **集合**:长度动态可变,支持自动扩容或缩容。例如,`ArrayList` 可在运行时添加元素。 ```java ArrayList<Integer> list = new ArrayList<>(); list.add(10); // 添加元素 list.add(20); // 动态扩容 list.remove(0); // 删除元素,长度自动调整 ``` **关键点**:数组适合已知固定大小的场景(如矩阵计算),而集合适用于元素数量不确定的应用(如用户输入处理)[^1][^2]。 #### 2. **存储类型基本类型 vs 对象引用)** - **数组**:可直接存储基本数据类型(如 `int`, `char`)或对象引用(如 `String`)。 ```java int[] intArr = {1, 2, 3}; // 存储基本类型int String[] strArr = {"a", "b", "c"}; // 存储对象引用 ``` - **集合**:只能存储对象引用,基本类型需使用包装类(如 `Integer`, `Character`)。 ```java ArrayList<Integer> intList = new ArrayList<>(); intList.add(1); // 自动装箱为Integer对象 // ArrayList<int> invalid = ... // 错误:不能直接存储基本类型 ``` **关键点**:数组更高效用于数值计算(避免装箱开销),而集合强制面向对象设计[^2][^3]。 #### 3. **类型安全(编译时检查)** - **数组**:编译时不强制类型检查,可能导致运行时错误(如 `ClassCastException`)。 ```java Object[] objArr = new Integer[2]; objArr[0] = 10; // 合法 objArr[1] = "error"; // 运行时错误:ClassCastException ``` - **集合**:通过泛型(Generics)在编译时强制类型安全,减少错误。 ```java ArrayList<String> strList = new ArrayList<>(); strList.add("hello"); // 合法 // strList.add(100); // 编译错误:类型不匹配(Integer vs String) ``` **关键点**:集合的泛型机制提升代码健壮性,特别适合大型项目[^2]。 #### 4. **内存分配访问效率** - **数组**:元素存储在连续内存块中,索引访问时间复杂度为 $O(1)$(常量时间),适合高频随机访问。 ```java int[] arr = {10, 20, 30}; System.out.println(arr[1]); // 输出20,直接索引高效访问 ``` - **集合**:内存布局因实现而异: - `ArrayList` 基于数组,访问快($O(1)$),但插入/删除慢(需移动元素); - `LinkedList` 基于链表,访问慢($O(n)$),但插入/删除快; - `HashSet` 基于哈希表,访问平均 $O(1)$,但不保证顺序。 ```java LinkedList<Integer> linkedList = new LinkedList<>(); linkedList.add(10); linkedList.add(20); System.out.println(linkedList.get(1)); // 输出20,但需遍历链表(O(n)) ``` **关键点**:数组在性能敏感场景(如数值算法)更优;集合提供灵活的底层实现选择[^2][^4]。 #### 5. **功能方法与操作灵活性** - **数组**:仅支持基础操作(索引读写),复杂功能需借助工具类(如 `Arrays.sort()`)。 ```java int[] arr = {3, 1, 2}; Arrays.sort(arr); // 使用Arrays工具类排序 ``` - **集合**:内置丰富方法(添加、删除、排序、过滤等),通过接口(如 `List`, `Set`)扩展功能。 ```java ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 2)); list.add(4); // 直接添加元素 Collections.sort(list); // 使用Collections排序 list.removeIf(n -> n > 2); // 条件删除 ``` **关键点**:集合简化了数据操作(如批量处理),而数组需额外编码[^1][^4]。 #### 6. **元素唯一性与集合类型** - **数组**:始终允许重复元素。 ```java int[] arr = {1, 1, 2}; // 合法,元素可重复 ``` - **集合**:行为取决于具体子类: - `List`(如 `ArrayList`)允许重复; - `Set`(如 `HashSet`)强制唯一性。 ```java HashSet<Integer> set = new HashSet<>(); set.add(1); set.add(1); // 重复元素自动忽略 System.out.println(set); // 输出[1] ``` **关键点**:集合通过接口支持多样化需求(如去重使用 `Set`)[^2][^4]。 #### 7. **相互转换** 数组集合可互转,但需注意类型兼容: - **数组集合**:使用 `Arrays.asList()`(返回固定大小列表)。 ```java String[] arr = {"a", "b", "c"}; List<String> list = Arrays.asList(arr); // 数组转List list.set(0, "d"); // 修改列表会影响原数组 ``` - **集合数组**:使用 `toArray()` 方法。 ```java ArrayList<String> list = new ArrayList<>(); list.add("x"); String[] arr = list.toArray(new String[0]); // 集合数组 ``` **关键点**:转换涉及浅拷贝,适用于数据互通场景[^2][^3]。 ### 总结 - **使用数组**:当元素数量固定、需高性能访问(如数值计算)或存储基本类型时。 - **使用集合**:当元素数量动态变化、需高级操作(如排序、过滤)或类型安全时。集合框架(如 `List`, `Set`, `Map`)提供了更现代的API设计[^4]。 实际开发中,集合更常用(覆盖95%的场景),但数组在底层优化或遗留代码中仍有价值。 相关问题: 1. Java中如何高效地将数组转换为 `ArrayList`? 2. 在哪些场景下使用数组集合更有优势? 3. 集合框架中的 `List` `Set` 接口有何核心差异?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值