5、Java核心API系列(三)

四、集合框架

1、集合框架概述

Java集合框架为Java应用程序提供了数据结构的实现,这些数据结构如接口、类和算法是为了处理对象集合的一种统一的方式。集合框架的核心接口主要包括:Collection、List、Set、Queue和Map。

  1. Collection接口
    • 定义:是所有集合的根接口,定义了集合的基本操作,如添加、移除、遍历等。
    • 子接口:List、Set、Queue等。
    • 方法:
      • add(E e):添加元素。
      • remove(Object o):移除元素。
      • contains(Object o):检查元素是否存在。
      • isEmpty():检查集合是否为空。
      • size():返回集合元素的数量。
      • iterator():返回集合的迭代器,用于遍历集合。
  2. 层次结构
    • Collection接口下分为List和Set两个分支。
      • List:元素有序,允许重复。
      • Set:元素无序,不允许重复。

2、 List接口及其实现类

List接口表示一个有序且允许重复元素的集合。主要实现类有ArrayList、LinkedList和Vector。

  1. ArrayList

    • 特点:

      • 内部基于动态数组实现,支持快速随机访问。
      • 不支持同步,线程不安全。
    • 性能:适用于需要频繁访问和修改元素的场景。

    • 示例代码:

      List list = new ArrayList<>();  
      list.add("Apple");  
      list.add("Banana");  
      System.out.println(list.get(0)); // 输出:Apple  
      
  2. LinkedList

    • 特点:

      • 内部基于双向链表实现,适合频繁插入和删除操作。
      • 同样不支持同步,线程不安全。
    • 性能:插入和删除操作比ArrayList高效,但随机访问较慢。

    • 示例代码:

      List list = new LinkedList<>();  
      list.add("Dog");  
      list.add("Cat");  
      System.out.println(list.remove(0)); // 输出:Dog  
      
  3. Vector

    • 特点:

      • 同ArrayList类似,但所有方法都是同步的,线程安全。
      • 性能较ArrayList差。
    • 适用场景:在需要线程安全的多线程环境中使用。

    • 示例代码:

      List list = new Vector<>();  
      list.add("Car");  
      list.add("Bike");  
      System.out.println(list.size()); // 输出:2  
      
  4. 比较与选择

    • ArrayList:适用于大部分需要快速随机访问和修改的场景。
    • LinkedList:适用于频繁插入和删除操作的场景。
    • Vector:适用于多线程环境中对线程安全要求较高的场景。
  5. 常用方法

    • add(E e):添加元素。
    • get(int index):获取指定索引的元素。
    • indexOf(Object o):返回元素的首次出现的索引。
    • remove(int index):移除指定索引的元素。

3、Set接口及其实现类

Set接口表示一个不允许重复元素的无序集合。主要实现类有HashSet、TreeSet和LinkedHashSet。

  1. HashSet

    • 特点:

      • 内部基于哈希表实现,不保证元素的顺序。
      • 不支持同步,线程不安全。
    • 性能:提供快速的搜索和插入操作。

    • 示例代码:

      Set set = new HashSet<>();  
      set.add("Pen");  
      set.add("Pen"); // 重复元素不会被添加  
      System.out.println(set.contains("Pen")); // 输出:true  
      
  2. TreeSet

    • 特点:

      • 内部基于树结构实现,元素排列有序。
      • 同样不支持同步,线程不安全。
    • 性能:插入和删除操作的性能较低,但适合需要有序的集合。

    • 示例代码:

      Set set = new TreeSet<>();  
      set.add(10);  
      set.add(5);  
      set.add(15);  
      System.out.println(set); // 输出:[5, 10, 15]  
      
  3. LinkedHashSet

    • 特点:

      • 内部同时使用哈希表和链表,保持元素的插入顺序。
      • 不支持同步,线程不安全。
    • 性能:在哈希表的基础上维护链表,插入和访问性能稍低于HashSet。

    • 示例代码:

      Set set = new LinkedHashSet<>();  
      set.add("Orange");  
      set.add("Grape");  
      System.out.println(set); // 输出:[Orange, Grape]  
      
      
  4. 比较与选择

    • HashSet:适用于需要快速查找且不关心顺序的场景。
    • TreeSet:适用于需要保持元素排序的场景。
    • LinkedHashSet:适用于需要保持插入顺序的场景。
  5. 常用方法

    • add(E e):添加元素,如果集合中已有该元素则不添加。
    • contains(Object o):检查集合是否包含该元素。
    • isEmpty():检查集合是否为空。

4、Map接口及其实现类

Map接口表示键值对集合,其中键是唯一的,值可以重复。主要实现类有HashMap、TreeMap和LinkedHashMap。

  1. HashMap

    • 特点:

      • 基于哈希表实现,不保证键的顺序。
      • 线程不安全。
    • 性能:在哈希函数实现上高度优化,查找和插入操作非常高效。

    • 示例代码:

      Map map = new HashMap<>();  
      map.put("John", 30);  
      map.put("Mary", 25);  
      System.out.println(map.get("John")); // 输出:30  
      
  2. TreeMap

    • 特点:

      • 基于红黑树实现,键保持有序排列。
      • 同样不支持同步,线程不安全。
    • 性能:查找和插入操作的时间复杂度为O(log n)。

    • 示例代码:

      Map map = new TreeMap<>();  
      map.put("Banana", 10);  
      map.put("Apple", 5);  
      System.out.println(map.keySet()); // 输出:[Apple, Banana]  
      
  3. LinkedHashMap

    • 特点:

      • 内部同时使用哈希表和链表,保持键的插入顺序。
      • 可以配置缓存策略,如LRU(最近最少使用)算法。
    • 性能:在保留顺序的同时,仍然保持较高的查找效率。

    • 示例代码:

      Map map = new LinkedHashMap<>();  
      map.put("China", "Beijing");  
      map.put("USA", "Washington");  
      System.out.println(map.keySet()); // 输出:[China, USA]  
      
  4. 比较与选择

    • HashMap:适用于不需要键顺序,仅需快速查找和更新的场景。
    • TreeMap:适用于需要保持键有序排列的场景。
    • LinkedHashMap:适用于需要保持键插入顺序,或者需要实现缓存策略的场景。
  5. 常用方法

    • put(K key, V value):添加或更新键值对。
    • get(Object key):获取指定键对应的值。
    • containsKey(Object key):检查集合是否包含该键。
    • entrySet():返回键值对的集合视图。

5、集合的优化与设计模式

  1. 集合的性能优化

    • 选择合适的集合类:根据具体需求选择List、Set或Map的不同实现类,以确保操作的高效性。
    • 初始容量设置:如ArrayList和HashMap支持初始化容量,合理设置初始容量可以减少扩容操作,提升性能。
    • 减少扩容:频繁的添加操作可能导致集合扩容,应尽量减少不必要的扩容。
    • 使用适当的数据结构:例如,使用Stack而不是List进行栈操作,使用Queue而不是List进行队列操作。
  2. 集合相关的设计模式

    • 观察者模式:在Java集合中,可以通过注册Listener接口来监控集合的变化,如添加或移除元素时通知所有注册的Listener。
    • 适配器模式:用于将不兼容的集合接口转换为所需的接口,以适应不同的使用场景。
    • 迭代器模式:集合提供的Iterator接口即是迭代器模式的应用,允许用户在不了解集合内部实现的情况下遍历集合元素。
  3. 示例:观察者模式在集合中的应用

    • 在Java Swing库中,许多集合类型支持添加Listener来监听集合的变化。
    • 可自定义实现Observer接口,用于处理集合修改事件。
    import java.util.Observable;  
    import java.util.Observer;  
    
    public class ObservableList extends Observable {  
        private List list = new ArrayList<>();  
    
        public void addElement(String element) {  
            list.add(element);  
            setChanged();  
            notifyObservers(element);  
        }  
    
        public static void main(String[] args) {  
            ObservableList observableList = new ObservableList();  
            Observer observer = new Observer() {  
                @Override  
                public void update(Observable o, Object arg) {  
                    System.out.println("Added element: " + arg);  
                }  
            };  
            observableList.addObserver(observer);  
            observableList.addElement("New Element");  
        }  
    }  
    

总结

Java集合框架为开发者提供了丰富的数据结构实现,使得处理对象集合更加高效和方便。通过理解和掌握不同集合接口及其实现类的特点和常用方法,开发者可以在实际项目中根据具体需求选择合适的集合类,提升程序的性能和可维护性。此外,合理应用集合的优化策略和设计模式,可以进一步优化程序的结构和功能,实现更高效的开发和维护。

你可能感兴趣的:(java,windows)