当前位置: 首页 > 面试题库 >

自定义HashMap代码问题

徐峰
2023-03-14
问题内容

我有以下代码,其中我使用HashMap(使用两个并行数组)存储键值对(键可以具有多个值)。现在,我必须存储和加载它以备将来使用,这就是为什么我使用文件通道存储和加载它的原因。此代码的问题是:我可以在我的8
GB服务器中存储近1.2亿个键值对(实际上,我可以为JVM分配8 GB中的近5 GB,而这两个并行阵列需要近2.5
GB,其他内存用于我的代码的各种处理)。但是,我必须存储近600/700百万个键值对。anybdoy可以帮助我如何修改此代码,从而使我可以存储近600/700百万个键值对。或对此发表任何评论对我都很好。还有一点,我必须将哈希映射加载并存储到内存中。使用文件通道需要花费很长时间。根据堆栈溢出的各种建议,我没有找到更快的一个。我使用了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以外的其他位置。



 类似资料:
  • MIP 的事件机制和数据驱动机制基本已经满足了大部分的交互需求,但在一些复杂的需求下面,单单依靠简单的 MIP 表达式无法进行更为复杂的计算,因此引入 mip-script 组件来扩充 MIP 表达式的计算能力。 提示: 本篇仅简要介绍了 mip-script 与 mip-data,有关 mip-script 的详细用法、属性说明等内容,请查看 mip-script 的组件说明。 mip-scri

  • 我考虑在项目中使用fluent-http。 所以我尝试注入: 返回正确的字符串,但似乎没有使用状态代码。在这两种情况下,响应都有一个代码HTTP200。 注意:我发现一些状态代码是预先实现的: null

  • 开发者可以在 mip-script 中编写 JS 代码来扩展 MIP 数据驱动机制的计算能力。 标题 内容 类型 通用 支持布局 nodisplay 所需脚本 https://c.mipcdn.com/static/v2/mip-script/mip-script.js 组件间通信是常见的需求,除了通过使用事件来实现组件通信之外,实际上,有一部分组件通信的需求是可以直接用数据来完成的,通常推荐直接

  • 在代码片段的开始和结束加上表示,有了这个表示以后,就可以展开和折叠 自定义代码库如下所示 //<editor-fold desc="Description"> findViewById(R.id.btnLoading).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View

  • EasySwoole支持自定义添加一个socket资源参与系统底层的事件调度循环,添加事件循环与swoole原生的EventLoop一致,这里只做简单介绍,扩展应用请参照swoole文档 // 函数原型 bool swoole_event_add(int $sock, mixed $read_callback, mixed $write_callback = null, int $flags =

  • 我试图改变visual studio代码中基本类型的颜色。我改变了字体的颜色,比如