【java】java笔记总结——java API | 泛型 | 集合框架

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

一、java API

1.1、概念

Java API (Application Programming Interface) 提供了许多预构建的类、接口和异常处理方法,用于开发Java应用程序。这些类和接口是为了完成特定任务而设计的,比如:

文件 I/O(如File、InputStream、OutputStream等)

网络编程(如Socket、ServerSocket等)

数据库连接(JDBC)

用户界面组件(Swing或JavaFX)

集合类(如List、Set、Map等)

多线程处理(如Thread、Runnable等)

数据和时间处理等(如LocalDate、LocalTime等)

所有这些类和接口都是按照相关的包(package)进行组织的,这样可以方便开发者找到需要的类或接口。使用Java API,开发者可以避免从零开始编写所有代码,从而提高开发效率和代码质量。

1.2、java.lang

java.lang 是 Java 编程语言的核心包(Package),它提供了Java程序最基础和核心的类。这个包中的类和接口会被自动导入到所有的Java程序中,无需开发者手动导入。
java.lang 包包含许多重要的类,例如:

Object:这是类层次结构的根类,所有的类都继承自这个类。

String:用于创建和操作字符串。

StringBuilder 和 StringBuffer:用于创建可修改的字符串。

Math:提供了执行基本数学运算的方法,如平方根、绝对值等。

System:提供了访问环境变量、输入输出流、加载文件等系统级别的功能。

Thread:用于创建和操作线程,实现多线程编程。

Exception、Error 等:用于处理和定义错误和异常。

还有一些基本的包装类型,如 Integer、Long、Double、Boolean等,都是在 java.lang 包中定义的。这些包装类为基本数据类型提供了类级别的功能。
总的来说,java.lang 包提供了编写Java程序所必需的基本类和接口。


既然java的八大数据类型都有了 还要创造他们的封装类?
Java为其8个基本数据类型(byte, short, int, long, float, double, char, boolean)提供了对应的包装类(Byte, Short, Integer, Long, Float, Double, Character, Boolean)。这么做有几个主要原因:

对象操作:基本数据类型是原始类型,不是对象。有时我们需要将它们视为对象,例如在泛型、集合框架中,只能使用对象。

空值表示:基本数据类型不能是null,而它们的包装类可以。这对于表示值可能不存在的情况很有用。

实用方法:包装类提供了一些实用方法,例如将字符串转换为数字、判断一个字符是否是数字等。

类成员默认值:类的成员变量有默认值,基本类型有自己的默认值(如 int 的默认值是 0),而对象的默认值是 null。使用包装类型可以区分未初始化和默认值。

自动装箱和拆箱:Java 5 引入了自动装箱和拆箱特性,允许程序员自动或隐式地在基本数据类型和其对应的包装类之间转换。

例如:

List<Integer> list = new ArrayList<>();
list.add(5);  // 这里发生自动装箱,将 int 类型的 5 装箱成 Integer 类型

int number = list.get(0);  // 这里发生自动拆箱,将 Integer 类型拆箱为 int 类型

包装类在Java编程中是非常有用的,因为它们允许更灵活和高级的操作和表示。


java.lang.Math 和 java.math的区别
java.lang.Math 和 java.math 是 Java 中两个不同的包,它们的功能和使用场景不同。

java.lang.Math:这是 Java 的核心类库中的一个类,提供了一系列静态方法用于执行基本的数学运算,如三角函数、对数、乘方、平方根等。它还提供了用于生成随机数、四舍五入等操作的方法。由于这个类在 java.lang 包中,因此无需手动导入就可以在任何 Java 程序中使用。

java.math:这是一个包,包含了一些类(如 BigInteger 和 BigDecimal),这些类用于执行超过了基本数类型(例如 int、long、double)限制的数学运算。例如,当你需要进行非常大的整数计算,或者需要高精度的浮点数计算时,就需要使用这个包里的类。这些类提供了一系列方法来进行加法、减法、乘法、除法等操作。

总结来说,java.lang.Math 提供了基本的数学运算,而 java.math 提供了更高级的、超出基本类型限制的数学运算功能。


java.util包是干啥的
java.util 是 Java 中的一个包,它包含了许多实用工具类和接口,主要用于实现数据结构、算法和时间日期处理。以下是 java.util 包中一些主要的类和接口:

集合相关的类和接口:如 List、ArrayList、LinkedList、Set、HashSet、TreeSet、Map、HashMap、TreeMap 等。这些类和接口用于存储和操作数据。

日期和时间相关的类:如 Date、Calendar、TimeZone 等。这些类用于表示和操作日期和时间。

其他实用工具类:如 Random(用于生成随机数)、Timer 和 TimerTask(用于调度任务)、Observable 和 Observer(用于实现观察者模式)等。

枚举类:如 Enumeration、Iterator、ListIterator,这些用于枚举(遍历)数据集合。

函数式接口:Java 8 引入的新特性,如 Function、Consumer、Predicate 等,这些在进行函数式编程时非常有用。

java.util 包是编写 Java 程序时经常需要使用的一个包,它提供了许多重要的数据结构和算法

二、泛型

2.1.概念

Java 泛型是 JDK 5.0 引入的一个新特性,主要用于代码的类型安全和消除类型强制转换。

类型安全:泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型集合会接收什么类型的对象,编译器可以在编译时确保正确类型的对象被用于方法调用,从而减少运行时错误。

消除类型转换:在泛型中,你不需要类型转换。你可以将一个类型的对象视为另一种类型,运行时的类型检查和自动类型转换将由编译器完成。

我可以为你提供几个关于 Java 泛型的例子:
例子1:泛型类

public class Box<T> {
    
    
    private T t;

    public void set(T t) {
    
     this.t = t; }
    public T get() {
    
     return t; }
}

Box<Integer> integerBox = new Box<>();
integerBox.set(123);

Box<String> stringBox = new Box<>();
stringBox.set("Hello World");

在上述代码中,Box 是一个泛型类,可以用于存储各种类型的对象。当创建 Box 对象时,我们需要指定存储的类型。
例子2:泛型接口

interface Pair<K, V> {
    
    
    public K getKey();
    public V getValue();
}

class OrderPair<K, V> implements Pair<K, V> {
    
    
    private K key;
    private V value;

    public OrderPair(K key, V value) {
    
    
        this.key = key;
        this.value = value;
    }

    public K getKey() {
    
     return key; }
    public V getValue() {
    
     return value; }
}

OrderPair<String, Integer> p1 = new OrderPair<>("Even", 8);
OrderPair<String, String>  p2 = new OrderPair<>("hello", "world");

在这个例子中,Pair 是一个具有两个类型参数的泛型接口,OrderPair 类实现了这个接口。
例子3:泛型方法

public class Util {
    
    
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
    
    
        return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue());
    }
}

Pair<Integer, String> p1 = new OrderPair<>(1, "apple");
Pair<Integer, String> p2 = new OrderPair<>(2, "pear");
boolean same = Util.<Integer, String>compare(p1, p2);

在这个例子中,Util.compare() 是一个泛型方法,它可以用于比较任何类型的 Pair 对象。
这些例子展示了 Java 泛型的灵活性,使用泛型可以帮助你编写更通用、更安全的代码。

2.2.java中的泛型和C++的模板异同点

Java的泛型和C++的模板在很多方面是相似的,它们都是提供了一种方式来编写一般化的代码,这样就可以处理各种类型的数据,而不是为每种类型单独编写代码。这有助于代码复用和类型安全。
然而,它们在实现和功能上有一些重要的区别:

编译时机:在C++中,模板是在编译时实例化的。当你使用一个特定类型的模板时,编译器会为那个类型生成一个新的模板实例。这意味着如果你用很多不同类型使用了模板,那么编译后的代码可能会变得相当大。
相反,Java的泛型使用类型擦除实现。这意味着在编译时,所有的泛型信息都会被移除,只留下原始类型。这可以使生成的字节码更小,但也意味着一些类型信息在运行时不可用。

功能:C++的模板更强大,它们可以用于类、函数和变量,并且支持模板特化和部分特化。这使得模板可以用于非常复杂和高级的编程技巧。
相比之下,Java的泛型主要用于类和方法,功能较为简单。泛型在Java中的主要目的是提高类型安全和代码可读性,而不是提供高级的编程技巧。

总的来说,尽管Java的泛型和C++的模板在概念上相似,但是它们在具体的实现和用途上有一些重要的差别。

三、集合框架

3.1.概念

Java 集合框架提供了一系列用于存储和管理数据的类和接口。这个框架主要包括接口、实现(类)和算法。

主要接口:主要有 Collection、List、Set、Queue、Deque、Map 等。这些接口分别定义了各种集合应具备的行为。例如,List 是有序的、可重复的集合,而 Set 是无序的、不可重复的集合。

主要实现:ArrayList、LinkedList、HashSet、LinkedHashSet、TreeSet、HashMap、LinkedHashMap、TreeMap 等。这些类提供了各种类型的数据结构,如动态数组、链表、哈希表、树等。

算法:这些是静态方法,主要在 Collections 类中,提供了各种操作,如排序、查找、同步控制等。

下面是这些主要接口和实现的一个简单的概述:

List 接口:有序、可重复的集合。例如,ArrayList 和 LinkedList 是这个接口的常见实现。ArrayList 是基于动态数组实现的,查找快,增删慢;LinkedList 是基于双向链表实现的,增删快,查找慢。

Set 接口:无序、不可重复的集合。例如,HashSet、LinkedHashSet 和 TreeSet。HashSet 基于哈希表实现,有很快的存取速度;TreeSet 基于红黑树实现,元素有序;LinkedHashSet 维护了一个运行于所有条目的双向链表,提供了顺序性。

Map 接口:键值对的集合。例如,HashMap、TreeMap 和 LinkedHashMap。HashMap 提供了快速的查询,但没有任何顺序;TreeMap 按照键进行排序;LinkedHashMap 保持了键插入的顺序。

Queue 和 Deque 接口:队列和双端队列。例如,LinkedList、ArrayDeque、PriorityQueue 等。LinkedList 和 ArrayDeque 可以作为队列或者双端队列使用;PriorityQueue 是一个优先队列,元素会按照自然顺序或者提供的比较器进行排序。

这只是集合框架的简单概述,实际使用中还需要根据具体需求选择合适的集合类型。并且,大多数集合类都支持泛型,可以用来存储任何类型的对象。

3.2.Collection接口

在 Java 中,Collection 是 Java 集合框架的基础接口,它是 List、Set 和 Queue 接口的父接口。这个接口声明了存储一组对象的通用方法。
这些方法包括:

add(E e): 确保此集合包含指定的元素。

addAll(Collection<? extends E> c): 将指定集合中的所有元素添加到此集合。

clear(): 移除此集合中的所有元素。

contains(Object o): 如果此集合包含指定的元素,则返回 true。

containsAll(Collection<?> c): 如果此集合包含指定集合中的所有元素,则返回 true。

isEmpty(): 如果此集合不包含元素,则返回 true。

iterator(): 返回此集合中的元素的迭代器。

remove(Object o): 如果存在,移除此集合中的指定元素。

removeAll(Collection<?> c): 移除此集合中包含在指定集合中的所有元素。

retainAll(Collection<?> c): 仅保留此集合中包含在指定集合中的元素。

size(): 返回此集合中的元素数量。

toArray(): 返回包含此集合中所有元素的数组。

注意,Collection 接口本身并不支持直接访问元素,或者说没有提供获取指定位置元素的方法,这是由它的子接口 List 提供的。对于无序集合(例如 Set)来说,元素的位置没有实际意义,因此 Collection 接口没有提供直接访问元素的方法。
当你需要一个集合时,一般会使用 Collection 接口的某个子接口,例如 List、Set 或 Queue,这些接口提供了更具体的行为。对于每个子接口,Java 都提供了一些实现类,如 ArrayList、HashSet、LinkedList 等。

3.3.List 接口

在 Java 中,List 接口是 Collection 接口的一个重要子接口,它表示一个元素有序并且可以重复的集合。
List 接口定义了一些特定于列表的操作,如按照位置索引访问元素、搜索元素、迭代列表等。下面是一些重要的 List 接口的方法:

void add(int index, E element): 在列表的指定位置插入指定的元素。

boolean add(E e): 将指定的元素追加到此列表的末尾。

E get(int index): 返回列表中指定位置的元素。

int indexOf(Object o): 返回此列表中首次出现的指定元素的索引,如果此列表不包含该元素,则返回 -1。

int lastIndexOf(Object o): 返回此列表中最后出现的指定元素的索引,如果此列表不包含该元素,则返回 -1。

ListIterator listIterator(): 返回此列表元素的列表迭代器(按适当顺序)。

E remove(int index): 移除此列表中指定位置的元素。

E set(int index, E element): 用指定的元素替换此列表中指定位置的元素。

List 接口有几个常用的实现类,包括 ArrayList、LinkedList 和 Vector。

ArrayList:基于动态数组实现,提供了快速随机访问,但在列表中间插入和删除元素的速度比较慢。

LinkedList:基于双向链表实现,提供了快速的插入和删除操作,但随机访问的速度较慢。

Vector:类似于 ArrayList,但它是同步的,可以用在多线程环境,但性能上会比 ArrayList 慢。

选择哪个实现类取决于你的具体需求。例如,如果你需要频繁访问元素,ArrayList 是一个好选择;如果你需要频繁插入和删除元素,那么 LinkedList 可能更合适。

3.4.Set接口

在 Java 中,Set 接口是 Collection 接口的一个子接口,它代表一个不包含重复元素的集合。也就是说,每个元素只能出现一次。
Set 接口主要的方法继承自 Collection,并没有添加任何新的方法,但它有几个重要的实现类,包括 HashSet、LinkedHashSet 和 TreeSet,这些实现类提供了各种类型的行为:

HashSet:基于哈希表实现,这是最常用的 Set 实现类。它不保证元素的顺序,允许使用 null 元素,提供了快速访问元素的能力。

LinkedHashSet:维护了一个运行于所有条目的双向链表,因此它可以输出元素的插入顺序。相比于 HashSet,它的迭代性能更佳,但插入和删除元素时稍慢。

TreeSet:基于红黑树(一种自平衡的二叉查找树)实现,元素会以升序进行排序(如果添加了自定义的比较函数,也可以按照自定义的顺序排序),但访问和操作的时间复杂度为 O(log(n))。

注意,尽管 Set 接口继承了 Collection 接口的 add、remove 和 contains 方法,但 Set 的行为与 Collection 有所不同,特别是对 add 方法。当你尝试添加一个已存在于 Set 中的元素时,add 方法会返回 false,并且 Set 不会被改变,而 Collection 则会允许添加重复的元素。

3.5.Map 接口

在 Java 中,Map 接口不是 Collection 接口的子接口,它代表一个映射关系,可以存储键值对(key-value pair)。键和值都可以是任何类型的对象,键不能重复,但值可以。
Map 接口定义了一些操作键值对的方法,如下:

void clear(): 移除所有的映射。

boolean containsKey(Object key): 如果此映射包含指定键的映射关系,则返回 true。

boolean containsValue(Object value): 如果此映射将一个或多个键映射到指定值,则返回 true。

Set<Map.Entry<K, V>> entrySet(): 返回此映射中包含的映射关系的 Set 视图。

V get(Object key): 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

boolean isEmpty(): 如果此映射未包含键-值映射关系,则返回 true。

Set keySet(): 返回此映射中包含的键的 Set 视图。

V put(K key, V value): 将指定的值与此映射中的指定键关联。

void putAll(Map<? extends K, ? extends V> m): 从指定映射中将所有映射关系复制到此映射中。

V remove(Object key): 如果存在一个键的映射关系,则将其从此映射中移除。

int size(): 返回此映射中的键-值映射关系数。

Collection values(): 返回此映射中包含的值的 Collection 视图。

Map 接口有一些常见的实现类,包括 HashMap、LinkedHashMap、TreeMap 和 Hashtable:

HashMap:基于哈希表的实现,这是最常用的 Map 实现类。它不保证映射的顺序,允许使用 null 值和 null 键。

LinkedHashMap:维护了一个运行于所有条目的双向链表,因此可以按照插入顺序或访问顺序(LRU)来迭代映射。

TreeMap:基于红黑树(一种自平衡的二叉查找树)实现,它会根据键的自然顺序或者创建时提供的 Comparator 来排序所有的键值对。

Hashtable:与 HashMap 类似,但不允许使用 null 键和 null 值,而且是同步的。

在选择使用哪种 Map 实现类时,需要考虑你的需求,例如是否需要排序,是否允许 null 键和值,是否需要考虑多

猜你喜欢

转载自blog.csdn.net/weixin_46274756/article/details/131276214