如何创建JAVA集合时指定一个合适的初始容量,以减少扩容的次数

       在创建集合时指定一个合适的初始容量可以显著减少扩容的次数,从而提高性能。以下是一些常见集合类型的建议和示例代码,帮助你在创建集合时指定合适的初始容量。

1. ArrayList

  • 建议:如果你预计集合将存储大量元素,可以在创建 ArrayList 时指定一个较大的初始容量。例如,如果你知道集合最终将包含1000个元素,可以将初始容量设置为1000或稍大一些。
  • 示例代码
    import java.util.ArrayList;
    
    public class ArrayListExample {
        public static void main(String[] args) {
            int initialCapacity = 1000; // 预计的元素数量
            ArrayList<String> list = new ArrayList<>(initialCapacity);
    
            for (int i = 0; i < 1000; i++) {
                list.add("Element " + i);
            }
    
            System.out.println("List size: " + list.size());
        }
    }

2. HashMap

  • 建议:对于 HashMap,初始容量和负载因子是两个重要的参数。初始容量应设置为预期元素数量除以负载因子(默认为0.75),并向上取整到最近的2的幂次方。例如,如果你预计集合将包含1000个键值对,可以将初始容量设置为1000 / 0.75 ≈ 1334,然后取最近的2的幂次方1024。
  • 示例代码
    import java.util.HashMap;
    
    public class HashMapExample {
        public static void main(String[] args) {
            int expectedSize = 1000; // 预计的键值对数量
            float loadFactor = 0.75f; // 默认负载因子
            int initialCapacity = (int) Math.ceil(expectedSize / loadFactor);
            initialCapacity = Integer.highestOneBit(initialCapacity - 1) << 1; // 取最近的2的幂次方
    
            HashMap<String, String> map = new HashMap<>(initialCapacity);
    
            for (int i = 0; i < 1000; i++) {
                map.put("Key " + i, "Value " + i);
            }
    
            System.out.println("Map size: " + map.size());
        }
    }

3. HashSet

  • 建议HashSet 内部使用 HashMap,因此其初始容量的计算方法与 HashMap 相同。如果你预计集合将包含1000个元素,可以将初始容量设置为1000 / 0.75 ≈ 1334,然后取最近的2的幂次方1024。
  • 示例代码
    import java.util.HashSet;
    
    public class HashSetExample {
        public static void main(String[] args) {
            int expectedSize = 1000; // 预计的元素数量
            float loadFactor = 0.75f; // 默认负载因子
            int initialCapacity = (int) Math.ceil(expectedSize / loadFactor);
            initialCapacity = Integer.highestOneBit(initialCapacity - 1) << 1; // 取最近的2的幂次方
    
            HashSet<String> set = new HashSet<>(initialCapacity);
    
            for (int i = 0; i < 1000; i++) {
                set.add("Element " + i);
            }
    
            System.out.println("Set size: " + set.size());
        }
    }

4. Vector

  • 建议Vector 与 ArrayList 类似,但默认情况下新容量是旧容量的两倍。你可以根据预期的元素数量来设置初始容量。例如,如果你预计集合将包含1000个元素,可以将初始容量设置为1000。
  • 示例代码
    import java.util.Vector;
    
    public class VectorExample {
        public static void main(String[] args) {
            int initialCapacity = 1000; // 预计的元素数量
            Vector<String> vector = new Vector<>(initialCapacity);
    
            for (int i = 0; i < 1000; i++) {
                vector.add("Element " + i);
            }
    
            System.out.println("Vector size: " + vector.size());
        }
    }

5. ConcurrentHashMap

  • 建议ConcurrentHashMap 的初始容量和负载因子的计算方法与 HashMap 相同。此外,还可以指定并发级别(concurrency level),这会影响内部段的数量。如果你预计集合将包含1000个键值对,可以将初始容量设置为1000 / 0.75 ≈ 1334,然后取最近的2的幂次方1024。
  • 示例代码
    import java.util.concurrent.ConcurrentHashMap;
    
    public class ConcurrentHashMapExample {
        public static void main(String[] args) {
            int expectedSize = 1000; // 预计的键值对数量
            float loadFactor = 0.75f; // 默认负载因子
            int initialCapacity = (int) Math.ceil(expectedSize / loadFactor);
            initialCapacity = Integer.highestOneBit(initialCapacity - 1) << 1; // 取最近的2的幂次方
            int concurrencyLevel = 16; // 并发级别
    
            ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
    
            for (int i = 0; i < 1000; i++) {
                map.put("Key " + i, "Value " + i);
            }
    
            System.out.println("Map size: " + map.size());
        }
    }

6. CopyOnWriteArrayList

  • 建议CopyOnWriteArrayList 在每次修改时都会创建一个新的数组副本,因此初始容量的设置尤为重要。如果你预计集合将包含1000个元素,可以将初始容量设置为1000。
  • 示例代码
    import java.util.concurrent.CopyOnWriteArrayList;
    
    public class CopyOnWriteArrayListExample {
        public static void main(String[] args) {
            int initialCapacity = 1000; // 预计的元素数量
            CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(new String[initialCapacity]);
    
            for (int i = 0; i < 1000; i++) {
                list.add("Element " + i);
            }
    
            System.out.println("List size: " + list.size());
        }
    }

7. CopyOnWriteArraySet

  • 建议CopyOnWriteArraySet 内部使用 CopyOnWriteArrayList,因此其初始容量的设置方法与 CopyOnWriteArrayList 相同。如果你预计集合将包含1000个元素,可以将初始容量设置为1000。
  • 示例代码
    import java.util.concurrent.CopyOnWriteArraySet;
    
    public class CopyOnWriteArraySetExample {
        public static void main(String[] args) {
            int initialCapacity = 1000; // 预计的元素数量
            CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>(new String[initialCapacity]);
    
            for (int i = 0; i < 1000; i++) {
                set.add("Element " + i);
            }
    
            System.out.println("Set size: " + set.size());
        }
    }

总结

  • 基于数组的集合(如 ArrayListVectorCopyOnWriteArrayList)可以通过指定初始容量来减少扩容次数。
  • 基于哈希表的集合(如 HashMapHashSetConcurrentHashMap)需要考虑负载因子,并将初始容量设置为预期元素数量除以负载因子,再取最近的2的幂次方。
  • 基于链表或树的集合(如 LinkedListTreeSet)不需要指定初始容量,因为它们是动态扩展的。

       通过合理设置初始容量,可以显著减少集合的扩容次数,提高程序的性能。特别是对于大型数据集和高性能要求的应用,这一点尤为重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山高自有客行路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值