和 HashMap 一样,Hashtable 也是一个散列表,它存储的内容是键值对。
Hashtable 在 Java 中的定义为:
1 | public class Hashtable<K,V> |
从源码中我们可以看出:
- Hashtable继承于Dictionary类 —— 任何可将键值映射到相应值的类的一种抽象父类。每个键和值都是对象。
- 实现了Map<K,V>, Cloneable, java.io.Serializable 接口
和 HashMap 一样,Hashtable 也是一个散列表,它存储的内容是键值对。
Hashtable 在 Java 中的定义为:
1 | public class Hashtable<K,V> |
从源码中我们可以看出:
在学系统设计的时候设计到了缓存过期算法。在此详细研究一下介个。
本文主要参考自详解三种缓存过期策略LFU,FIFO,LRU(附带实现代码)
缓存机制:先分配一定的缓存空间。使用数据的时候先查询缓存空间中是否有该数据的缓存。如果有的话直接拿出来。如果没有的话去其它地方查询,然后同时将查询到的结果放入缓存空间,方便下次调用。伪代码如下:
1 | def getUser(user_id): |
缓存机制就像上面所说的那样。cache
一般是有有效期的,也就是如果缓存中这个数据过期了,那就从缓存中清理出去。而cache
的实现过程和淘汰机制不同,会导致不同的性能表现。常见的就是IFIO,LRU,LFU缓存过期策略。
大纲
大纲
求m ~ n之间所有数字的与。
思路:一开始就是暴力与。但这样超时了。
参考资料[LeetCode] Bitwise AND of Numbers Range 数字范围位相与
我们先从题目中给的例子来分析,[5, 7]里共有三个数字,分别写出它们的二进制为:
101 110 111
相与后的结果为100,仔细观察我们可以得出,最后的数是该数字范围内所有的数的左边共同的部分,如果上面那个例子不太明显,我们再来看一个范围[26, 30],它们的二进制如下:
11010 11011 11100 11101 11110
发现了规律后,我们只要写代码找到左边公共的部分即可。
直接平移m和n,每次向右移一位,直到m和n相等,记录下所有平移的次数i,然后再把m左移i位即为最终结果,代码如下:
1 | public int rangeBitwiseAnd(int m, int n) { |
给一个数组,数组中只有一个元素是单个出现的,其它都是成对出现。找到这个元素。
思路:由于x ^ 0 = x, x ^ x = 0 , 因此 x ^ x ^ y ^ z ^ z = y
1 | public int singleNumber(int[] nums) { |
将无符号整数按位反转。
1 | public int reverseBits(int n) { |
求一个无符号整数的1bit的个数
1 | public int hammingWeight(int n) { |
给一些str。求两个没有共有字母的word的长度乘积的最大值。
1 | public int maxProduct(String[] words) { |
输入n,给定以下操作:
求一个n变为1的最少操作次数
思路一,递归
1 | private int helper(long n){ |
思路二,位操作
首先,对于任意偶数,只有一个选择,即除以2,总的步数增加1。然后,对于任意奇数,无论加一或者减一,得到的必然是偶数,依然还要要除以2,步数增加2。所以归结的问题是,奇数到底是加一还是需要减一呢?
举一个简单的例子,数字5,当5+1=6时,明显不如5-1=4快,因为6除以2后又是一个奇数3,对比5-1得到的4,需要额外的两步变为4 (5->6->3->4 vs 5->4),或者多一步数变为2 (5->6->3->2 vs 5->4->2)。其实上,数字尽可能为偶数,是最快的。
如上所述,奇数无论加减1,如果得到的数能被4整除(偶数的2倍),那么就是快的。对于任意奇数,可以写成4n+1或者4n+3的形式。适当加一或者减一,总有可能被4整除,所以实际中只要测试其中一种运算即可。这里面要考虑一个特例:3变4,因为3->2->1结束。
1 | public int integerReplacement(int n) { |
改进版:
1 | public int integerReplacement(int n) { |
给两个整数,计算两个整数的二进制汉明距离
1 | public int hammingDistance(int x, int y) { |
另一种方式:
1 | public int hammingDistance(int x, int y) { |
系统设计面试
HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是不保证该顺序恒久不变。
此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get和put)提供稳定的性能。
迭代colletction视图所需要的时间与HashMap实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以如果迭代性能很重要,则不能将初始容量设置得太高,或者将加载因子设置的太低。
需要注意的是,HashMap是不同步的。如果多个线程同时访问一个HashMap,若其中某个线程修改了HashMap的结构(即删除或者添加映射关系),那么必须要保持外部同步。
大纲