目录

Java集合_八股场景题

Java集合_八股&场景题

Java集合

在Java开发中,集合框架是面试和实际开发中非常重要的内容。以下是一些常见的Java集合八股文问题和场景题,以及详细答案和示例代码。


1. Java集合框架的结构是什么?

答案:

Java集合框架主要分为三大接口: CollectionMapQueue

  • Collection :是集合的顶级接口,它又分为 ListSet
    • List :有序集合,允许重复元素,如 ArrayListLinkedListVector
    • Set :无序集合,不允许重复元素,如 HashSetLinkedHashSetTreeSet
  • Map :键值对集合,不允许键重复,但值可以重复,如 HashMapTreeMapLinkedHashMap
  • Queue :队列接口,用于实现先进先出(FIFO)的集合,如 LinkedListPriorityQueue

示例代码:

import java.util.*;

public class CollectionFramework {
    public static void main(String[] args) {
        // List
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        System.out.println("List: " + list);

        // Set
        Set<String> set = new HashSet<>();
        set.add("Java");
        set.add("Python");
        System.out.println("Set: " + set);

        // Map
        Map<String, Integer> map = new HashMap<>();
        map.put("Java", 1);
        map.put("Python", 2);
        System.out.println("Map: " + map);

        // Queue
        Queue<String> queue = new LinkedList<>();
        queue.add("Java");
        queue.add("Python");
        System.out.println("Queue: " + queue);
    }
}

2. ArrayList和LinkedList的区别是什么?

答案:

  • 存储结构
    • ArrayList 基于动态数组实现,支持快速随机访问,但插入和删除效率较低。
    • LinkedList 基于双向链表实现,插入和删除效率高,但不支持快速随机访问。
  • 性能差异
    • ArrayList 适合频繁读取, LinkedList 适合频繁插入和删除。
  • 内存占用
    • LinkedList 每个节点需要额外存储前后指针,内存占用较大。

示例代码:

import java.util.*;

public class ArrayListVsLinkedList {
    public static void main(String[] args) {
        // ArrayList
        List<String> arrayList = new ArrayList<>();
        arrayList.add("Java");
        arrayList.add("Python");
        System.out.println("ArrayList: " + arrayList.get(0)); // 快速随机访问

        // LinkedList
        List<String> linkedList = new LinkedList<>();
        linkedList.add("Java");
        linkedList.add("Python");
        linkedList.add(0, "C++"); // 插入操作
        System.out.println("LinkedList: " + linkedList);
    }
}

3. HashMap的底层实现原理是什么?

答案:

HashMap 基于哈希表实现,主要由两部分组成:数组和链表(或红黑树)。

  • 哈希冲突 :当两个键的哈希值相同或哈希值对数组取模后相同,会发生冲突。
  • 解决冲突
    • JDK 1.7及之前:链表法,将冲突的元素存储在链表中。
    • JDK 1.8及之后:链表+红黑树,当链表长度超过8时,链表会转换为红黑树,以优化查找效率。
  • 扩容机制 :当负载因子( size / capacity )达到阈值(默认0.75)时,数组会扩容为原来的两倍。

示例代码:

import java.util.*;

public class HashMapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("Java", 1);
        map.put("Python", 2);
        map.put("Java", 3); // 键重复,值覆盖
        System.out.println("HashMap: " + map);

        // 遍历
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

4. 如何保证线程安全?HashMap、ArrayList和Vector的区别是什么?

答案:

  • 线程安全
    • HashMapArrayList 不是线程安全的,需要手动同步。
    • Vector 是线程安全的,但性能较差,因为它的每个方法都加了 synchronized 锁。
  • 区别
    • HashMapArrayList :非线程安全,性能高。
    • Vector :线程安全,性能低。
  • 线程安全的替代品
    • 使用 Collections.synchronizedMap()ConcurrentHashMap 替代 HashMap
    • 使用 CopyOnWriteArrayList 替代 ArrayList

示例代码:

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ConcurrentHashMap;

public class ThreadSafeCollections {
    public static void main(String[] args) {
        // 线程安全的Map
        Map<String, Integer> map = new ConcurrentHashMap<>();
        map.put("Java", 1);

        // 线程安全的List
        List<String> list = new CopyOnWriteArrayList<>();
        list.add("Java");

        System.out.println("Thread-safe Map: " + map);
        System.out.println("Thread-safe List: " + list);
    }
}

5. 如何实现一个线程安全的单例集合?

答案:

可以通过 Collections.synchronizedList()Collections.synchronizedMap() 实现线程安全的集合。

还可以使用 CopyOnWriteArrayListConcurrentHashMap

示例代码:

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class SingletonCollection {
    private static SingletonCollection instance;
    private List<String> list;

    private SingletonCollection() {
        list = new CopyOnWriteArrayList<>();
    }

    public static SingletonCollection getInstance() {
        if (instance == null) {
            synchronized (SingletonCollection.class) {
                if (instance == null) {
                    instance = new SingletonCollection();
                }
            }
        }
        return instance;
    }

    public void addElement(String element) {
        list.add(element);
    }

    public List<String> getElements() {
        return list;
    }

    public static void main(String[] args) {
        SingletonCollection singleton = SingletonCollection.getInstance();
        singleton.addElement("Java");
        System.out.println("Elements: " + singleton.getElements());
    }
}

6. 如何实现一个自定义的排序集合?

答案:

可以通过实现 Comparable 接口或使用 Comparator 接口对集合进行排序。

示例代码:

import java.util.*;

class Person implements Comparable<Person> {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person other) {
        return Integer.compare(this.age, other.age); // 按年龄升序排序
    }

    @Override
    public String toString() {
        return name + ": " + age;
    }
}

public class CustomSort {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("Alice", 25));
        list.add(new Person("Bob", 30));
        list.add(new Person("Charlie", 20));

        Collections.sort(list); // 使用Comparable接口排序
        System.out.println("Sorted by age: " + list);

        // 使用Comparator接口排序
        list.sort(Comparator.comparingInt(p -> p.age));
        System.out.println("Sorted by age using Comparator: " + list);
    }
}

7. 如何实现一个去重的集合?

答案:

可以使用 Set 接口实现去重,如 HashSetLinkedHashSet

示例代码:

import java.util.*;

public class UniqueCollection {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("Java");
        list.add("C++");

        Set<String> set = new HashSet<>(list);
        System.out.println("Unique elements: " + set);
    }
}

8. 如何实现一个缓存集合?

答案:

可以使用 LinkedHashMap 实现一个简单的LRU(最近最少使用)缓存。

示例代码:

import java.util.*;

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

    public LRUCache(int capacity