gpt4 book ai didi

java - 自定义 HashMap 代码问题

转载 作者:行者123 更新时间:2023-11-30 09:35:19 25 4
gpt4 key购买 nike

我有以下代码,其中我使用 HashMap(使用两个并行数组)来存储键值对(键可以有多个值)。现在,我必须存储和加载它以供将来使用,这就是我使用文件 channel 存储和加载它的原因。这段代码的问题是:我可以在我的 8 GB 服务器中存储近 1.2 亿个键值对(实际上,我可以为我的 JVM 分配 8 GB 中的近 5 GB,而这两个并行数组占用近 2.5 GB,其他内存用于我的代码的各种处理)。但是,我必须存储近 600/7 亿个键值对。任何人都可以帮助我如何修改此代码,以便我可以存储近 600/7 亿个键值对。或者对此的任何评论对我来说都会很好。还有一点,我必须将散列图加载到内存或从内存中存储。使用文件 channel 需要一点点时间。根据 Stack Overflow 的各种建议,我没有找到更快的建议。我也使用过 ObjectOutputStream,Zipped 输出流,但是比下面的代码慢。无论如何以这种方式存储这两个并行数组,从而加载时间会快得多。我在下面的代码中给出了一个测试用例。对此的任何评论也将对我有所帮助。

import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Arrays;
import java.util.Random;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.io.RandomAccessFile;

public class Test {

public static void main(String args[]) {


try {

Random randomGenerator = new Random();

LongIntParallelHashMultimap lph = new LongIntParallelHashMultimap(220000000, "xx.dat", "yy.dat");

for (int i = 0; i < 110000000; i++) {
lph.put(i, randomGenerator.nextInt(200000000));
}

lph.save();

LongIntParallelHashMultimap lphN = new LongIntParallelHashMultimap(220000000, "xx.dat", "yy.dat");
lphN.load();

int tt[] = lphN.get(1);

System.out.println(tt[0]);

} catch (Exception e) {
e.printStackTrace();
}
}
}

class LongIntParallelHashMultimap {

private static final long NULL = -1L;
private final long[] keys;
private final int[] values;
private int size;
private int savenum = 0;
private String str1 = "";
private String str2 = "";

public LongIntParallelHashMultimap(int capacity, String st1, String st2) {
keys = new long[capacity];
values = new int[capacity];
Arrays.fill(keys, NULL);
savenum = capacity;
str1 = st1;
str2 = st2;
}

public void put(long key, int value) {
int index = indexFor(key);
while (keys[index] != NULL) {
index = successor(index);
}
keys[index] = key;
values[index] = value;
++size;
}

public int[] get(long key) {
int index = indexFor(key);
int count = countHits(key, index);
int[] hits = new int[count];
int hitIndex = 0;

while (keys[index] != NULL) {
if (keys[index] == key) {
hits[hitIndex] = values[index];
++hitIndex;
}
index = successor(index);
}

return hits;
}

private int countHits(long key, int index) {
int numHits = 0;
while (keys[index] != NULL) {
if (keys[index] == key) {
++numHits;
}
index = successor(index);
}
return numHits;
}

private int indexFor(long key) {
return Math.abs((int) ((key * 5700357409661598721L) % keys.length));
}

private int successor(int index) {
return (index + 1) % keys.length;
}

public int size() {
return size;
}

public void load() {
try {
FileChannel channel2 = new RandomAccessFile(str1, "r").getChannel();
MappedByteBuffer mbb2 = channel2.map(FileChannel.MapMode.READ_ONLY, 0, channel2.size());
mbb2.order(ByteOrder.nativeOrder());
assert mbb2.remaining() == savenum * 8;
for (int i = 0; i < savenum; i++) {
long l = mbb2.getLong();
keys[i] = l;
}
channel2.close();

FileChannel channel3 = new RandomAccessFile(str2, "r").getChannel();
MappedByteBuffer mbb3 = channel3.map(FileChannel.MapMode.READ_ONLY, 0, channel3.size());
mbb3.order(ByteOrder.nativeOrder());
assert mbb3.remaining() == savenum * 4;
for (int i = 0; i < savenum; i++) {
int l1 = mbb3.getInt();
values[i] = l1;
}
channel3.close();
} catch (Exception e) {
System.out.println(e);
}
}

public void save() {
try {
FileChannel channel = new RandomAccessFile(str1, "rw").getChannel();
MappedByteBuffer mbb = channel.map(FileChannel.MapMode.READ_WRITE, 0, savenum * 8);
mbb.order(ByteOrder.nativeOrder());

for (int i = 0; i < savenum; i++) {
mbb.putLong(keys[i]);
}
channel.close();

FileChannel channel1 = new RandomAccessFile(str2, "rw").getChannel();
MappedByteBuffer mbb1 = channel1.map(FileChannel.MapMode.READ_WRITE, 0, savenum * 4);
mbb1.order(ByteOrder.nativeOrder());

for (int i = 0; i < savenum; i++) {
mbb1.putInt(values[i]);
}
channel1.close();
} catch (Exception e) {
System.out.println("IOException : " + e);
}
}
}

最佳答案

考虑到您声明的数据类型,我怀疑这是可能的。只需乘以基本类型的大小即可。

每行需要 4 个字节来存储 int 和 8 个字节来存储 long。6 亿行 * 每行 12 个字节 = 7200 MB = 7.03 GB。你说你可以为 JVM 分配 5 GB。所以即使它全部是堆并且只存储这个自定义的 HashMap,它也不适合。考虑缩小所涉及数据类型的大小或将其存储在 RAM 以外的地方。

关于java - 自定义 HashMap 代码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11398762/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com