List、Map、set的加载因子,默认初始容量和扩容增量 ...

本文深入探讨了Java中ArrayList、Vector、HashSet、HashMap和Hashtable等容器的初始大小、加载因子及扩容方式。详细分析了这些容器如何在元素数量达到一定阈值时进行内存扩容,并解释了不同容器的底层实现细节及其线程安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,这三个概念说下。初始大小,就是创建时可容纳的默认元素个数;加载因子,表示某个阀值,用0~1之间的小数来表示,当已有元素占比达到这个阀值后,底层将进行扩容操作;扩容方式,即指定每次扩容后的大小的规则,比如翻倍等。

当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使效率大大降低。

加载因子的系数小于等于1,意指  即当 元素个数 超过 容量长度*加载因子的系数 时,进行扩容。

另外,扩容也是有默认的倍数的,不同的容器扩容情况不同。

List 元素是有序的、可重复

ArrayList、Vector默认初始容量为10

Vector:线程安全,但速度慢

    底层数据结构是数组结构

    加载因子为1:即当 元素个数 超过 容量长度 时,进行扩容

    扩容增量:原容量的 1倍

      如 Vector的容量为10,一次扩容后是容量为20

ArrayList:线程不安全,查询速度快

    底层数据结构是数组结构

    扩容增量:原容量的 0.5倍+1

      如 ArrayList的容量为10,一次扩容后是容量为16

 

Set(集) 元素无序的、不可重复。

HashSet:线程不安全,存取速度快

     底层实现是一个HashMap(保存数据),实现Set接口

     默认初始容量为16(为何是16,见下方对HashMap的描述)

     加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容

     扩容增量:原容量的 1 倍

      如 HashSet的容量为16,一次扩容后是容量为32

 

构造方法摘要HashSet() 
HashSet(int initialCapacity)
构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。
HashSet hs=new HashSet(1);

所以可见 HashSet类,创建对象的时候是可以的制定容量的大小的 ,期中第二个就具有这个工功能。

 

Map是一个双列集合

HashMap:默认初始容量为16

     (为何是16:16是2^4,可以提高查询效率,另外,32=16<<1       -->至于详细的原因可另行分析,或分析源代码)

     加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容

     扩容增量:原容量的 1 倍

      如 HashSet的容量为16,一次扩容后是容量为32

Hashtable: 线程安全

     默认初始容量为11

     加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容

     扩容增量:原容量的 1 倍+1

      如 Hashtable的容量为11,一次扩容后是容量为23

 

Class

初始大小

加载因子

扩容倍数

底层实现

Code

是否线程安全

同步方式

ArrayList

10

1

1.5倍+1

Object数组

int newCapacity = oldCapacity + (oldCapacity >> 1)+1;
">>"右移符号,所以是除以2,所以新的容量是就的1.5倍+1
Arrays.copyOf 调用 System.arraycopy 扩充数组

线程不安全

-

Vector

10

1

2倍

Object数组

int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
capacityIncrement默认为0,所以是加上本身,也就是2*oldCapacity,2倍大小
Arrays.copyOf 调用 System.arraycopy 扩充数组

线程安全

synchronized

HashSet

16

0.75f

2倍

HashMap<E,Object>

add方法实际调用HashMap的方法put

线程不安全

-

HashMap

16

0.75f

2倍

Map.Entry

void addEntry(int hash, K key, V value, int bucketIndex) {
    if ((size >= threshold) && (null != table[bucketIndex])) {
        resize(2 * table.length);
        hash = (null != key) ? hash(key) : 0;
        bucketIndex = indexFor(hash, table.length);
    }

    createEntry(hash, key, value, bucketIndex);
}

线程不安全

-

Hashtable

11

0.75f

2倍+1

Hashtable.Entry数组

int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) {
    if (oldCapacity == MAX_ARRAY_SIZE)
        return;
    newCapacity = MAX_ARRAY_SIZE;
}

线程安全

synchronized

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

这是基于jdk1.7版本以前进行研究,jdk1.7以后有所改动

原文地址:https://www.cnblogs.com/lizhen-home/p/7352125.html

import numpy as np import matplotlib.pyplot as plt import pandas as pd def calc_distance(city1, city2): return np.linalg.norm(np.array(city1) - np.array(city2)) def calc_distances(cities): n_cities = len(cities) distances = np.zeros((n_cities, n_cities)) for i in range(n_cities): for j in range(i + 1, n_cities): distances[i][j] = distances[j][i] = calc_distance(cities[i], cities[j]) return distances class AntColony: def __init__(self, distances, n_ants, n_iterations, decay, alpha=1, beta=5, rho=0.1, Q=1): self.distances = distances self.pheromone = np.ones_like(distances) / len(distances) self.n_ants = n_ants self.n_iterations = n_iterations self.decay = decay self.alpha = alpha self.beta = beta self.rho = rho self.Q = Q self.shortest_path_lengths = [] def run(self): shortest_path = None shortest_path_length = np.inf for _ in range(self.n_iterations): all_paths = self.gen_all_paths() self.spread_pheromone(all_paths) shortest_path, shortest_path_length = self.get_shortest(all_paths, shortest_path, shortest_path_length) self.pheromone *= (1 - self.rho) self.shortest_path_lengths.append(shortest_path_length) return shortest_path, shortest_path_length def spread_pheromone(self, all_paths): for path in all_paths: for move in path: self.pheromone[move] += self.Q / self.distances[move] def gen_path_dist(self, path): total = 0 for move in path: total += self.distances[move] return total def gen_all_paths(self): all_paths = [] for _ in range(self.n_ants): path = self.gen_path() all_paths.append(path) return all_paths def gen_path(self): n_cities = len(self.distances) path = [] visited = set() start = np.random.randint(n_cities) visited.add(start) prev = start for _ in range(n_cities - 1): next_city = self.pick_city(prev, visited) path.append((prev, next_city)) prev = next_city visited.add(next_city) path.append((prev, start)) return path def pick_city(self, prev, visited): pheromone = np.copy(self.pheromone[prev]) pheromone[list(visited)] = 0 row = pheromone ** self.alpha * (1.0 / (self.distances[prev] + 1e-6) ** self.beta) norm_row = row / row.sum() next_city = np.random.choice(range(len(self.distances)), 1, p=norm_row)[0] return next_city def get_shortest(self, all_paths, shortest_path, shortest_path_length): for path in all_paths: path_dist = self.gen_path_dist(path) if path_dist < shortest_path_length: shortest_path = [(int(a), int(b)) for (a, b) in path] shortest_path_length = path_dist return shortest_path, shortest_path_length # 数据加载模块 try: df = pd.read_excel("TSP.xlsx", header=None) cities = df.iloc[:, [0, 1]].values assert cities.shape[1] == 2, "坐标数据必须包含X,Y两列" except FileNotFoundError: print("错误:Excel文件未找到,请检查以下事项:") print("1. 文件是否位于当前工作目录") print("2. 文件名是否为'100个城市的坐标.xlsx'") print("3. 文件扩展名是否正确(.xlsx)") exit() except Exception as e: print(f"数据加载失败:{str(e)}") exit() # 计算距离矩阵 distances = calc_distances(cities) # 参数设置 n_ants = 20 n_iterations = 1000 decay = 0.1 alpha = 1 beta = 2 rho = 0.1 Q = 1 # 创建并运行蚁群算法 ant_colony = AntColony(distances, n_ants, n_iterations, decay, alpha, beta, rho, Q) shortest_path, shortest_path_length = ant_colony.run() # 路径格式化函数 def format_path(path): path_order = [int(path[0][0])] + [int(move[1]) for move in path] if path_order[-1] == path_order[0]: path_order = path_order[:-1] return ','.join(map(str, path_order)) # 输出结果 print("最短路径序列:", format_path(shortest_path)) print("最短路径长度:", shortest_path_length) # 可视化设置 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 绘制迭代曲线 plt.figure(figsize=(10, 5)) plt.plot(range(1, n_iterations + 1), ant_colony.shortest_path_lengths) plt.xlabel('迭代次数') plt.ylabel('路径长度') plt.title('算法优化过程') plt.grid(True) plt.show() # 路径可视化函数 def plot_path(cities, path): path_order = [path[0][0]] + [move[1] for move in path] x, y = cities[path_order, 0], cities[path_order, 1] plt.figure(figsize=(12, 8)) # 绘制城市点并添加编号(从1开始) for idx, (xi, yi) in enumerate(cities): plt.scatter(xi, yi, color='red', s=6,zorder=2) plt.text(xi, yi, str(idx + 1), fontsize=8,ha='center',va='bottom', color='black',zorder=3) # 绘制路径连线 plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示 plt.rcParams['axes.unicode_minus'] = False plt.plot(x, y, linestyle='-', marker='o', color='blue', linewidth=1, markersize=4, zorder=1) plt.xlabel('X坐标', fontsize=12) plt.ylabel('Y坐标', fontsize=12) plt.title('TSP最优路线 城市编号(1-1000)', fontsize=14) plt.grid(True, linestyle='--', alpha=0.7) plt.tight_layout() plt.show() plot_path(cities, shortest_path)输出错误D:\python\space\.venv\Scripts\python.exe D:\python\space\8\6.py D:\python\space\8\6.py:43: RuntimeWarning: divide by zero encountered in scalar divide self.pheromone[move] += self.Q / self.distances[move] D:\python\space\8\6.py:77: RuntimeWarning: invalid value encountered in divide norm_row = row / row.sum() Traceback (most recent call last): File "D:\python\space\8\6.py", line 118, in <module> shortest_path, shortest_path_length = ant_colony.run() ^^^^^^^^^^^^^^^^ File "D:\python\space\8\6.py", line 33, in run all_paths = self.gen_all_paths() ^^^^^^^^^^^^^^^^^^^^ File "D:\python\space\8\6.py", line 54, in gen_all_paths path = self.gen_path() ^^^^^^^^^^^^^^^ File "D:\python\space\8\6.py", line 66, in gen_path next_city = self.pick_city(prev, visited) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\python\space\8\6.py", line 78, in pick_city next_city = np.random.choice(range(len(self.distances)), 1, p=norm_row)[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "numpy\\random\\mtrand.pyx", line 990, in numpy.random.mtrand.RandomState.choice ValueError: probabilities contain NaN 修改代码正确,提供修改之后的完整代码可直接运行
最新发布
05-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值