一 初始结合框架
1.什么是Java的集合框架
Java 的集合框架(Java Collection Framework,JCF)是 Java 标准库中的一部分,用于存储和操作一组数据。它提供了一些常用的数据结构和接口,用来高效管理和操作数据。Java 的集合框架位于 java.util
包中。
1.让我们来简单认识一下 Java 集合框架的主要组成部分和它们的用途:
1. 核心接口
Java 集合框架中定义了一些核心接口,它们是各种集合实现类的基础:
- Collection 接口: 所有集合的根接口,提供了集合的基本操作(如添加、删除、遍历等)。
- List 接口: 有序集合,允许重复元素。
- Set 接口: 不允许重复元素的集合。
- Queue 接口: 用于存储按照 FIFO(先进先出)顺序处理的元素。
- Deque 接口: 双端队列,支持在两端添加和移除元素。
- Map 接口: 不属于 Collection 接口体系,但常用于存储键值对映射。
2. 核心实现类
Java 集合框架中提供了接口的多种实现类,涵盖了不同的使用场景:
-
List 实现类
ArrayList
: 基于动态数组的实现,访问速度快,适合随机访问。LinkedList
: 基于双向链表的实现,插入和删除速度快,适合频繁的插入/删除操作。Vector
: 类似于ArrayList
,但线程安全。Stack
: 基于Vector
实现的栈,遵循 LIFO(后进先出)原则。
-
Set 实现类
HashSet
: 基于哈希表的实现,元素无序且不重复,插入和查找速度快。LinkedHashSet
: 具有插入顺序的HashSet
实现。TreeSet
: 基于红黑树的实现,元素有序(自然顺序或自定义比较器)。
-
Map 实现类
HashMap
: 基于哈希表的键值对存储,无序。LinkedHashMap
: 保留键值对的插入顺序。TreeMap
: 基于红黑树,键值对按键有序排列。Hashtable
: 类似HashMap
,但线程安全。
-
Queue 和 Deque 实现类
PriorityQueue
: 基于优先级的队列,元素按自然顺序或自定义顺序排列。ArrayDeque
: 基于数组的双端队列,适用于栈和队列操作。
3. 工具类
集合框架还提供了一些工具类,用于辅助操作集合:
Collections
: 提供了各种静态方法,如排序、查找、线程安全包装等。Arrays
: 用于数组的操作(如转换为集合、排序、搜索等)。
2.数据结构的概念
数据结构是计算机科学中的一个重要概念,指的是数据的存储、组织和管理方式,以便能够有效地访问和修改数据。选择适当的数据结构可以提高算法的效率,使得程序运行更快、占用更少的资源。简单来说,数据结构决定了数据如何被存储在计算机的内存中,如何被读取、操作和维护。
二 时间复杂度和空间复杂度
1.算法效率
如何判断一个算法的效率:
算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作 空间复杂度。 时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间, 在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎,但是计算机经过很长时间的发展,储存容量已经到达了一个很高的容量,所以现在对于空间复杂度已经无所谓了,不是很在乎。
2时间复杂度
时间复杂度是一个函数,定量描述了算法的运行时间,算法中基本操作的执行次数为时间复杂度。
2.1大O的渐进表示法:
结果为:
大O的渐进表示法的规则 :
- 用常数1取代运行时间中的所有加法常数。
- 在修改后的运行次数函数中,只保留最高阶项。
- 如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
3.空间复杂度
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度,空间复杂度基本算的是变量的个数,和时间复杂度的算法基本一样,也用大O渐进表示法。
示例一:
示例1使用了常数个额外空间,所以空间复杂度为 O(1)
示例二:
示例2动态开辟了N个空间,空间复杂度为 O(N)
三 初识泛型
泛型是一种允许在类、接口和方法中定义类型参数的特性。通过泛型,实例化时可以指定具体的类型,使代码变得更加灵活。
1.包装类
1.1基本数据类型对应的包装类
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
1.2 装箱和拆箱
装箱是将基本数据类型(如int
、char
)转换为对应的包装类对象(如Integer
、Character
)。
拆箱则是将包装类对象转换回基本数据类型。
1.3装箱
分为手动装修和自动装箱
手动装修
public class Test {
public static void main(String[] args) {
int a=10;
Integer a1=Integer.valueOf(a);
System.out.println(a);
}
自动拆箱
public class Test {
public static void main(String[] args) {
int b=11;
Integer c=b;
System.out.println(c);
1.4拆箱
分为手动拆箱和自动拆箱
手动装修
public class Test {
public static void main(String[] args) {
Integer a=10;
int b=a.intValue();
System.out.println(b);
}
自动拆箱
public class Test {
public static void main(String[] args) {
Integer a=10;
int c=a;
System.out.println(c);
大家猜一下这个代码的运行结果
public class Test {
public static void main(String[] args) {
Integer a=10;
Integer b=10;
System.out.println(a==b);
System.out.println("----------------");
Integer c=200;
Integer d=200;
System.out.println(c==d);
}
为什么结果会不一样呢?
所以让我们一起来看一下装箱是怎么操作的
我们可以看出有一个最大值和一个最小值,所以Integer是有范围的
如果不在这个范围内,则不会比较数值的大小,而是比较地址。
2.泛型
泛型就是适用于许多类型。
示例(没有用泛型方法)
class MyArray{
public Object[] array=new Object[10];
public void setValue(int pos,Object val){
array[pos]=val;
}
public Object getValue(int pos){
return (Object) array[pos];
}
}
public class Test2 {
public static void main1(String[] args) {
MyArray myArray=new MyArray();
myArray.setValue(1,"he");
String s=(String) myArray.getValue(1);
System.out.println(s);
}
(用了泛型方法)
class MyArray<E>{
public Object[] array=new Object[10];
public void setValue(int pos,E val){
array[pos]=val;
}
public E getValue(int pos){
return (E) array[pos];
}
}
public class Test2 {
public static void main(String[] args) {
MyArray<String> myArray=new MyArray<>();
myArray.setValue(1,"he");
String a=myArray.getValue(1);
System.out.println(a);
}
通过上例,我们可以看出,泛型的运用可以在实例化时具体指定类型,接收时不需要强转,非常的便利。
2.1泛型的语法
1.
class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
class Name<T1, T2, ..., Tn> {
}
class 泛型类名称<类型形参列表> extends 继承类 /* 这里可以使用类型参数 */ {
// 这里可以使用类型参数
}
2. class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
// 可以只使用部分类型参数
}
class MyArray<E>extends Name<E>{
public Object[] array=new Object[10];
public void setValue(int pos,E val){
array[pos]=val;
}
public E getValue(int pos){
return (E) array[pos];
}
}
public class Test2 {
public static void main(String[] args) {
MyArray<String> myArray=new MyArray<>();
myArray.setValue(1,"he");
String a=myArray.getValue(1);
System.out.println(a);
}
public static void main1(String[] args) {
MyArray myArray=new MyArray();
myArray.setValue(1,"he");
String s=(String) myArray.getValue(1);
System.out.println(s);
}
}
2.2泛型类的使用
泛型类的语法
泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
示例
MyArray<String> myArray=new MyArray<>();
后面的<>中写不写Integer都可以,因为编译器会自动推导出需要的类型实参为 Integer
3.泛型的上界
在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
语法:
class 泛型类名称<类型形参 extends 类型边界> {
...
}
示例:
class MyArray<E extends Number>{
public Object[] array=new Object[10];
public void setValue(int pos,E val){
array[pos]=val;
}
public E getValue(int pos){
return (E) array[pos];
}
}
Number的源代码
注:只接受 Number 的子类型作为 E 的类型实参
public class Test2 {
public static void main(String[] args) {
MyArray<String> myArray=new MyArray<>();
MyArray<Integer> myArray2=new MyArray<>();
myArray.setValue(1,"he");
String a=myArray.getValue(1);
System.out.println(a);
}
String会报错,因为Integer 是 Number 的子类型,String 不是 Number 的子类型。
4.泛型方法
class FindMax<E extends Comparable>{
public E findMax(E[] array){
E max=array[0];
for (int i = 0; i < array.length; i++) {
if(max.compareTo(array[i])>0){
array[i]=max;
}
}
return max;
}
}
public class TestGenergic {
public static void main(String[] args) {
FindMax<Integer> findMax=new FindMax<>();
Integer[] array = {1,2,3,4,45,5,6,8};
System.out.println(findMax.findMax(array));
}
}
希望能对大家有所帮助!!!!