Lesson8 Java集合框架

概述

  • Collection:存储一组不唯一无序的对象
  • List:存储一组不唯一有序(插入顺序)的对象
    • 访问集合中的元素可以根据元素的索引来访问。
  • Set:存储一组唯一无序的对象
    • 访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。
    • SortedSet是一个按照升序排列元素的Set。
  • Map:存储一组键值对象,提供key到value的映射
    • 访问时只能根据每项元素的 key 来访问其 value。
    • SortedMap是一个按照升序排列
    • key的Map

集合框架分为以下几个部分

  • 数据结构:List列表、Queue队列、Deque双端队列、Set集合、Map映射
  • 比较器:Comparator比较器和Comparable排序接口
  • 算法:Collections常用算法类、Arrays静态数组的排序、查找算法
  • 迭代器:Iterator通用迭代器、ListIterator针对 List 特化的迭代器

集合类的工具类:Collections类和Arrays类

  • Arrays:操作数组,提供搜索、排序、复制等静态方法。
public static void main(String[] args) {
	int[] array = new int[]{11, 4, 23, 16, 3, 1, 4};
	Arrays.sort(array);
	System.out.println(Arrays.toString(array));//[1, 3, 4, 4, 11, 16, 23]
}
  • Collections:操作集合,提供搜索、排序、线程安全化等操作。
    Collection 是集合的父类接口, Collections 类是集合的工具类;
public static void main(String[] args) {
	List list = new ArrayList();
	list.add(17);
	list.add(11);
	list.add(65);
	list.add(36);
	Collections.sort(list);
	System.out.println(list);//[11, 17, 36, 65]
}

Comparable和Comparator接口

Comparable和Comparator都是java的接口,Comparable在java.lang包下,而Comparator在java.util包下,两者功能都是排序。

Comparable 接口

  • 只要一个类实现了这个接口就可以意味着这个类支持排序。
  • 实现了这个类的接口的列表或者数组可以可以使用Collections.sort或Arrays.sort进行排序。
  • 该接口的定义
public interface Comparable<T>{
	public int compareTo(T o);   // 只用compareTo方法,实现这个接口的类必须要重写这个方法
}
  • 比较的规则
    • 如果该对象和指定比较的对象相等,那么返回0。
    • 如果该对象比指定比较的对象大,那么返回正数。
    • 如果该对象比指定比较的对象小,返回负数。
class Person implements Comparable<Person>{
	String name;
	int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	@Override
	public int compareTo(Person person) {
		return this.age - person.age;
	}
}
import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
	Person[] persons = new Person[]{new Person("tom", 20), new Person("jack", 12)};
	System.out.print("排序之前:");
	for (Person p : persons) {
		System.out.print("name:" + p.name + ", age:" + p.age + " ");
	}
	// 排序之后
	Arrays.sort(persons);
	System.out.println("排序之后:");
	for (Person p : persons) {
		System.out.print("name:" + p.name + ", age:" + p.age + " ");
	}
}

Comparator 接口

  • 如果我们想要控制某个类的次序,而这个类并没有继承Comparable接口,那么我们就可以使用Comparator接口; 因此可以说,Comparator接口是Comparable接口的挽救接口
  • 比较的规则:大致和上面的规则相同,但也有不同的地方。

Collection 接口

Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List
Pasted image 20241111162535.png

Set 接口

  • 添加到Set中的元素必须定义 equals 方法,以提供算法来判断欲添加进来的对象是否与已经存在的某对象相等,从而建立对象的唯一性。
  • 实现Set接口的类有HashSet,TreeSet
    Pasted image 20241111162620.png
public class SetDemo{
	public static void main(String[] argv){
		HashSer<String> h = new HashSet<String>();
		// 也可以 Set h = new HashSet()
		h.add("one");
		h.add("Two");
		h.add("one");  // DUPLICATE
		h.add("Three");
		Iterator<String> it = h.iterator();
		while(it.hasNext()){
			System.ou.println(it.next());
		}
	}
}
Three
One
Two

List 接口

  • 实现它的类有ArrayList和LinkedList。
    • ArrayList
      • 顺序存储
      • 长度可变
      • 遍历元素和随机访问元素的效率比较高
    • LinkedList
      • 链表
      • 插入、删除元素时效率比较高

ArrayList

  • boolean add(Object o):在列表的末尾顺序添加元素,起始索引位置从0开始
  • void add(int index, Object o):在指定的索引位置添加元素。索引位置必须介于0和列表中元素个数之间
  • int size():返回列表中的元素个数
  • Object get(int index):返回指定索引位置处的元素。取出的元素是Object类型,使用前需要进行强制类型转换
  • boolean contains(Object o):判断列表中是否存在指定元素
  • boolean remove(Object o):从列表中删除指定元素
  • Object remove(int index):从列表中删除指定位置元素,起始索引位置从0开始

Pasted image 20241111163655.png
Pasted image 20241111163709.png
Pasted image 20241111163717.png

LinkedList

  • void addFirst(Object o):在列表的首部添加元素
  • void addLast(Object o):在列表的末尾添加元素
  • Object getFirst():返回列表中的第一个元素
  • Object getLast():返回列表中的最后一个元素
  • Object removeFirst()删除并返回列表中的第一个元素
  • Object removeLast()删除并返回列表中的最后一个元素

Pasted image 20241111163655.png
Pasted image 20241111164036.png
Pasted image 20241111164041.png

Map接口

  • 最常用的实现类是HashMap

  • Object put(Object key, Object val):以“键-值对”的方式进行存储

  • Object get (Object key)根据键返回相关联的值,如果不存在指定的键,返回null

  • Object remove (Object key)删除由指定的键映射的“键-值对”

  • int size():返回元素个数

  • Set keySet ():返回的集合

  • Collection values ():返回的集合

  • Boolean containsKey (Object key):如果存在由指定的键映射的“键-值对”,返回true

集合类对比

  • Vector和ArrayList的异同

    • 实现原理相同,功能相同,很多情况下可以互用
    • 两者的主要区别如下
      • Vector线程安全,ArrayList重速度轻安全,线程非安全
      • 长度需增长时,Vector默认增长一倍,ArrayList增长50%
  • Hashtable和HashMap的异同

    • 实现原理相同,功能相同,在很多情况下可以互用
    • 两者的主要区别如下
      • Hashtable继承Dictionary类,HashMap实现Map接口
      • Hashtable线程安全,HashMap线程非安全
      • Hashtable不允许null值,HashMap允许null值

迭代器Iteraor——用于遍历集合

  • 所有集合接口和类都没有提供相应遍历方法,而是由Iterator实现集合遍历
  • Collection 接口的iterate()方法返回一个Iterator,然后通过Iterator接口的两个方法可实现遍历
    • boolean hasNext(): 判断是否存在另一个可访问的元素
    • Object next(): 返回要访问的下一个元素

泛型

泛型类和接口

泛型类和接口允许定义一个或多个类型参数。这些参数在类或接口被实例化时指定,用于指定类或接口中使用的具体类型。

// 泛型类
public class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

// 泛型接口
public interface Pair<K, V> {
    public K getKey();
    public V getValue();
}
public interface Pair<K, V> {
    public K getKey();
    public V getValue();
}

// 实现泛型接口
public class StringIntegerPair implements Pair<String, Integer> {
    private String key;
    private Integer value;

    public StringIntegerPair(String key, Integer value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public Integer getValue() {
        return value;
    }
}

// 使用泛型接口
public class Main {
    public static void main(String[] args) {
        Pair<String, Integer> pair = new StringIntegerPair("Key", 123);
        System.out.println("Key: " + pair.getKey() + ", Value: " + pair.getValue());
    }
}

泛型方法

泛型方法可以定义在普通类或泛型类中,方法参数和返回值可以是泛型类型。

public class Util {
    // 泛型方法
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }
}
public class Util {
    // 泛型方法
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }
}

// 使用泛型方法
public class Main {
    public static void main(String[] args) {
        String[] stringArray = {"Hello", "Generics", "Java"};
        Util.printArray(stringArray);

        Integer[] integerArray = {1, 2, 3, 4, 5};
        Util.printArray(integerArray);
    }
}

类型参数命名约定

  • E - 元素(Element),例如在集合中使用。
  • K - 键(Key),例如在映射中使用。
  • V - 值(Value),例如在映射中使用。
  • T - 类型(Type),通用类型。
  • UVW 等 - 第二个、第三个、第四个类型。

通配符类型

通配符类型用于表示未知的类型。主要有三种形式:

  • ? - 无界通配符,表示未知类型。
public class Util {
    // 使用通配符类型的方法
    public static void printCollection(Collection<?> collection) {
	    // 使用通配符类型 ?,意味着它可以接受任何类型的 Collection。
	    // 这使得方法更加通用,可以接受不同类型的 Collection 实例。
        for (Object element : collection) {
            System.out.println(element);
        }
    }
}

// 使用通配符类型的方法
public class Main {
    public static void main(String[] args) {
        Collection<String> stringCollection = Arrays.asList("Hello", "Generics", "Java");
        Util.printCollection(stringCollection);

        Collection<Integer> integerCollection = Arrays.asList(1, 2, 3, 4, 5);
        Util.printCollection(integerCollection);
    }
}
  • ? extends T - 上界通配符,表示上界为 T 的类型。
public void processNumbers(List<? extends Number> list) {
    // ...
}
// processNumbers 方法可以接受任何 Number 类型的子类型的 List,如 Integer、Double 等。
  • ? super T - 下界通配符,表示下界为 T 的类型。
public void addNumbers(List<? super Integer> list) {
    // ...
}
// addNumbers 方法可以接受任何 Integer 类型的父类型的 List,如 Number、Object 等。

泛型的限制

  • 不能使用基本类型作为泛型参数。
  • 不能创建泛型数组。
  • 不能实例化泛型类型。
  • 不能在静态上下文中使用类型参数。

泛型的优点

  • 提高类型安全性:编译时检查类型,减少运行时错误。
  • 提高代码可重用性:无需为每种类型编写不同的代码。
  • 提高代码可读性:通过类型参数明确指出类、接口或方法操作的数据类型。
Built with MDFriday ❤️