集合(java集合框架)

Java 集合框架包含以下类和接口:

  1. Collection 接口:Collection 是所有集合接口的基本接口,定义了集合对象的通用操作,如添加元素、删除元素、判断集合是否为空、获取集合大小等。

  1. List 接口:List 是一个有序的集合接口,允许重复元素。常见的实现类有 ArrayList、LinkedList 和 Vector。

  1. Set 接口:Set 是一个不允许重复元素的集合接口,常见的实现类有 HashSet、TreeSet 和 LinkedHashSet。

  1. Queue 接口:Queue 是一个允许在队列尾部添加元素,在队列头部删除元素的集合接口。常见的实现类有 LinkedList 和 PriorityQueue。

  1. Map 接口:Map 是一个 key-value 对的集合接口,允许使用 key 查找 value,常见的实现类有 HashMap、TreeMap 和 LinkedHashMap。

  1. SortedSet 接口:SortedSet 是一个有序的不允许重复元素的集合接口,常见的实现类有 TreeSet。

  1. SortedMap 接口:SortedMap 是一个有序的 key-value 对的集合接口,允许使用 key 查找 value,常见的实现类有 TreeMap。

除了这些基本接口和实现类,Java 集合框架还包含了一些辅助类和接口,如 Iterator、ListIterator、Comparator、Collections 等。这些类和接口可以帮助我们更方便地操作集合,提高开发效率。


  1. List

List是一个有序的集合,可以通过索引访问其中的元素,可以有重复的元素。常见的实现类有ArrayList、LinkedList和Vector。

ArrayList是一个基于动态数组实现的List,当我们需要随机访问其中的元素时,它比LinkedList要快。而LinkedList则是基于双向链表实现的,当我们需要在其中进行添加或删除元素时,它比ArrayList要快。Vector与ArrayList类似,但它是线程安全的,所以当我们需要在多线程环境下使用时,可以选择使用Vector。

1.1 ArrayList

ArrayList 实现了 List 接口,可以动态地增加或缩小容量。内部使用数组来存储元素,所以支持随机访问,时间复杂度为 O(1)。

下面是一个简单的 ArrayList 示例:

List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
System.out.println(list); // 输出 [apple, banana, orange]

1.2 LinkedList

LinkedList 也实现了 List 接口,但是使用链表来存储元素。相比于 ArrayList,LinkedList 更适合于插入和删除操作,因为只需要改变链表节点的指针指向即可,时间复杂度为 O(1)。

下面是一个简单的 LinkedList 示例:

List<String> list = new LinkedList<>();
list.add("apple");
list.add("banana");
list.add("orange");
System.out.println(list); // 输出 [apple, banana, orange]

1.3 Vector

Vector 也实现了 List 接口,与 ArrayList 相似,但是 Vector 是线程安全的。不过,由于线程安全的代价较高,所以在单线程场景下,建议使用 ArrayList。

下面是一个简单的 Vector 示例:

List<String> list = new Vector<>();
list.add("apple");
list.add("banana");
list.add("orange");
System.out.println(list); // 输出 [apple, banana, orange]

  1. Set

Set是一个不允许有重复元素的集合。常见的实现类有HashSet、TreeSet和LinkedHashSet。

HashSet是基于散列表实现的Set,它是无序的,当我们需要进行快速查找元素时,可以选择使用它。TreeSet则是基于红黑树实现的Set,它是有序的,当我们需要进行排序操作时,可以选择使用它。LinkedHashSet是HashSet和LinkedList的混合体,它既可以快速查找元素,也可以保证元素的插入顺序。

2.1 HashSet

HashSet 内部使用 HashMap 实现,所以它的元素是无序的。如果要保持元素的插入顺序,建议使用 LinkedHashSet。

下面是一个简单的 HashSet 示例:

Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("orange");
set.add("apple"); // 添加重复元素,但是不会被存储
System.out.println(set); // 输出 [banana, orange, apple]

2.2 TreeSet

TreeSet 内部使用红黑树实现,所以它的元素是有序的。不过,相比于 HashSet,TreeSet 的插入、删除、查找操作都比较耗时,时间复杂度为 O(logn)。

下面是一个简单的 TreeSet 示例:

Set<String> set = new TreeSet<>();
set.add("apple");
set.add("banana");
set.add("orange");
System.out.println(set); // 输出 [apple, banana, orange]

2.3 LinkedHashSet

LinkedHashSet 继承了 HashSet 的特性,但是它可以保持元素的插入顺序。因为内部使用了一个双向链表来维护元素的插入顺序,所以相比于 HashSet,LinkedHashSet 在插入和遍历时的性能略微低一些,但是可以在保持元素插入顺序的同时快速访问某个元素。

LinkedHashSet 的构造方法与 HashSet 相同,可以通过指定初始容量和负载因子来创建实例。它也实现了 Set 接口,提供了与 HashSet 相同的操作方法。

以下是一个使用 LinkedHashSet 的示例代码:

LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("apple");
linkedHashSet.add("banana");
linkedHashSet.add("orange");

System.out.println(linkedHashSet); // [apple, banana, orange]

linkedHashSet.remove("banana");
System.out.println(linkedHashSet); // [apple, orange]

System.out.println(linkedHashSet.contains("apple")); // true

linkedHashSet.clear();
System.out.println(linkedHashSet); // []

从输出结果可以看到,LinkedHashSet 保持了元素插入的顺序,同时也提供了与 HashSet 相同的操作方法。

LinkedHashSet 在某些场景下非常有用,比如需要按照元素插入顺序遍历集合的情况。但是需要注意的是,由于 LinkedHashSet 内部使用了双向链表来维护元素插入顺序,因此它的内存占用比 HashSet 稍微高一些。

  1. Map

Map是一个key-value对的集合,key和value都可以是任何类型的对象。常见的实现类有HashMap、TreeMap和LinkedHashMap。

HashMap是基于散列表实现的Map,它是无序的,当我们需要进行快速查找元素时,可以选择使用它。TreeMap则是基于红黑树实现的Map,它是有序的,当我们需要进行排序操作时,可以选择使用它。LinkedHashMap则是HashMap和LinkedList的混合体,它既可以快速查找元素,也可以保证元素的插入顺序。

在使用集合类时,我们需要注意它们的时间复杂度和空间复杂度,选择合适的实现类。同时,我们还需要注意集合类的线程安全问题,如果在多线程环境下使用集合类,需要选择线程安全的实现类或使用同步机制进行保护。

3.1 HashMap

HashMap是一种基于散列表实现的Map集合,它通过将键值对映射到一个桶数组中来存储元素。当我们需要查找元素时,HashMap会通过计算键的哈希值来快速定位到对应的桶,从而达到快速查找的目的。

HashMap的实现是非常高效的,查找元素的时间复杂度为O(1)。但是由于其内部是通过哈希函数来计算键的哈希值的,因此它的键必须实现hashCode()和equals()方法。hashCode()方法用来计算键的哈希值,equals()方法用来判断两个键是否相等。如果两个键相等,则它们的哈希值也必须相等。

在使用HashMap时,我们需要注意以下几点:

  1. 初始容量和负载因子:HashMap的初始容量和负载因子可以在创建HashMap对象时指定,初始容量指的是HashMap中初始的桶的数量,负载因子指的是HashMap在自动扩容之前可以达到的平均填充因子。在实际使用中,我们需要根据元素的数量来选择合适的初始容量和负载因子,以保证HashMap的性能和空间利用率。

  1. 线程安全问题:HashMap是非线程安全的,如果在多线程环境下使用HashMap,需要进行同步保护。

  1. 遍历元素:HashMap提供了三种遍历元素的方式,分别是使用迭代器、使用键集合和值集合来遍历。使用迭代器遍历时,HashMap并不保证元素的顺序;使用键集合遍历时,HashMap保证元素的顺序与插入顺序相同;使用值集合遍历时,HashMap保证元素的顺序与键集合相同。

下面是一个使用HashMap的例子:

import java.util.HashMap;

public class HashMapExample {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Alice", 25);
        map.put("Bob", 30);
        map.put("Charlie", 35);

        System.out.println("Size of map: " + map.size());
        System.out.println("Age of Alice: " + map.get("Alice"));

        for (String key : map.keySet()) {
            System.out.println(key + " -> " + map.get(key));
        }
    }
}

输出:

Size of map: 3
Age of Alice: 25
Alice -> 25
Bob -> 30
Charlie -> 35

3.2 TreeMap

TreeMap 是一个基于红黑树实现的有序 Map,它根据键的自然顺序进行排序,或者根据用户指定的 Comparator 进行排序。TreeMap 内部维护了一棵红黑树,每个节点都是一个键值对。

TreeMap 的主要特点包括:

  • 排序:TreeMap 内部会自动根据键进行排序,可以自定义排序方式。

  • 线程不安全:和 HashMap 一样,TreeMap 是非线程安全的。

  • 实现 NavigableMap 接口:TreeMap 实现了 NavigableMap 接口,提供了一些便于操作有序映射的方法。

  • 数据结构是红黑树:红黑树是一种自平衡二叉查找树,保证了插入、删除、查找的时间复杂度均为 O(logN)。

使用 TreeMap 需要注意以下几点:

  • 键不能为 null:TreeMap 不允许键为 null,因为排序依赖键的值,如果键为 null,无法进行比较。

  • 自然排序和自定义排序:如果键实现了 Comparable 接口,则 TreeMap 会使用自然排序,否则需要提供一个 Comparator 进行自定义排序。

  • 性能:虽然 TreeMap 提供了有序的功能,但是在插入、删除等操作时,需要进行红黑树的操作,因此性能不如 HashMap。

下面是一个使用 TreeMap 的例子:

import java.util.TreeMap;

public class TreeMapDemo {

    public static void main(String[] args) {
        TreeMap<String, Integer> map = new TreeMap<>();

        // 添加元素
        map.put("apple", 10);
        map.put("banana", 5);
        map.put("orange", 8);

        // 遍历元素
        for (String key : map.keySet()) {
            System.out.println(key + " = " + map.get(key));
        }
    }
}

输出结果为:

apple = 10
banana = 5
orange = 8

从输出结果可以看出,TreeMap 内部按照键进行了排序,输出结果按照键的自然顺序进行排序。

3.3 LinkedHashMap

LinkedHashMap是Java中的一个Map集合,它是HashMap和LinkedList的结合体,具有HashMap的查询速度和LinkedList的顺序性,是一种既可以快速查找元素,又可以保证元素插入顺序的集合。

LinkedHashMap继承了HashMap的所有特性,也使用了哈希表来存储元素,但与HashMap不同的是,LinkedHashMap还维护了一个双向链表,用来保持插入顺序。每个Entry节点包含了指向前一个节点和后一个节点的指针,这样就可以按照插入的顺序遍历集合中的元素。

使用LinkedHashMap的时候,我们可以根据插入顺序或访问顺序来遍历元素,使用entrySet()方法可以获得一个包含Entry对象的Set集合,通过遍历这个集合,就可以按照插入顺序或访问顺序来遍历元素。如果希望按照访问顺序来遍历元素,可以在构造LinkedHashMap对象时传入accessOrder参数,并将其设置为true。

LinkedHashMap的性能和HashMap的性能基本一致,但是由于它需要维护双向链表,所以在内存消耗上会比HashMap多一些。如果我们需要保证元素插入顺序,或者需要按照插入顺序或访问顺序来遍历元素,可以考虑使用LinkedHashMap。

需要注意的是,由于LinkedHashMap维护了一个链表,所以它的插入、删除和查找操作都会比HashMap略微慢一些,尤其是在大量元素的情况下。因此,在选择集合实现类时,需要根据具体的需求来选择适合的实现类。

总之,LinkedHashMap是一种具有顺序性的Map集合,它能够快速查找元素,同时还能保证元素的插入顺序。在一些需要保证元素顺序的场合中,它可以起到很好的作用。

下面是一个使用LinkedHashMap的示例代码,实现了一个简单的LRU缓存:

import java.util.LinkedHashMap;
import java.util.Map;

public class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int MAX_ENTRIES;

    public LRUCache(int capacity) {
        super(capacity, 0.75f, true);
        MAX_ENTRIES = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > MAX_ENTRIES;
    }

    public static void main(String[] args) {
        LRUCache<Integer, String> cache = new LRUCache<>(3);
        cache.put(1, "one");
        cache.put(2, "two");
        cache.put(3, "three");
        System.out.println(cache);

        cache.put(4, "four");
        System.out.println(cache);

        cache.get(2);
        System.out.println(cache);

        cache.put(5, "five");
        System.out.println(cache);
    }
}

在这个例子中,LRUCache继承了LinkedHashMap,用于实现一个基于LRU算法的缓存。构造方法传入了一个容量,表示缓存中最多能够容纳的键值对数量。在removeEldestEntry方法中,如果当前的键值对数量超过了容量,就会返回true,表示需要删除最老的键值对,以保证容量不超限。在put和get操作中,由于继承了LinkedHashMap,所以会自动维护元素的插入顺序,从而实现了LRU算法的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值