>这可能是一个愚蠢的问题,但事情是这样的。我正在阅读这个问题:
存储 100 万个电话号码
被接受的问题是我在想的:使用 trie。在评论中,马特·鲍尔建议:
我认为将电话号码存储为 ASCII 文本并压缩是一个非常合理的建议
问题:如何在 Java 中做到这一点?ASCII 文本确实代表字符串?
对于问题中所示的内存存储:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter out = new OutputStreamWriter(
new GZIPOutputStream(baos), "US-ASCII");
for(String number : numbers){
out.write(number);
out.write('n');
}
byte[] data = baos.toByteArray();
但正如 Pete 所说:这可能有利于提高内存效率,但之后你无法真正对数据做任何事情,所以它并不是很有用。
是的,在这种情况下,ASCII 表示字符串。您可以使用java.util.zip.GZIPOutputStream将压缩数据存储在Java中。
回答一个隐含但不同的问题;
问:您有 10 亿个电话号码,需要通过低带宽连接发送这些号码。您只需要发送电话号码是否在集合中。 (无需其他信息)
答:这是一般做法
- 如果列表尚未排序,请先对列表进行排序。
- 从最低的数字中查找连续数字的区域。发送区域的开始和拍摄的电话。 这可以存储一个位集(每个可能的数字 1 位)在开始时发送电话号码,并在差距超过某个阈值时发送 BitSet。
- 将流写入压缩数据集。
- 测试此内容以与所有数字的简单发送进行比较。
可以在排序的树状图中使用字符串。 一百万个数字不是很多,将使用大约 64 MB。 我认为不需要更复杂的解决方案。
最新版本的 Java 可以通过使用 byte[] 而不是 char[] 来有效地存储 ASCII 文本,但是,数据结构的开销可能会更大。
如果需要将电话号码存储为密钥,则可以假设大范围将是连续的。因此,您可以像
NavigableMap<String, PhoneDetails[]>
在此结构中,键将定义范围的开始,您可以拥有每个号码的电话详细信息。 这可能不比对PhoneDetails的引用大多少(这是最小值)
顺便说一句:如果你不需要访问数据,你可以发明非常有效的结构。如果您从不访问数据,请不要将其保存在内存中,实际上您可以丢弃它,因为它永远不会被需要。
很大程度上取决于您要对数据执行的操作以及将其保存在内存中的原因。
您可以将DeflatorOutputStream用于ByteArrayOutputStream,这将非常小,但不是很有用。
我建议使用DeflatorOutputStream,因为它比GZIPOutputStream更轻/更快/更小。
Java 字符串默认采用 UTF-8 编码,如果要操作 ASCII 文本,则必须更改编码。