java:在hashmap中执行set,setbit,get和getbit

时间:2016-10-29 12:02:38

标签: java hashmap time-complexity

被修改

我正在尝试使用hashmap在我的程序中实现以下函数。

  • 获取

  • GETBIT

  • 设置
  • setBit

这是代码。

static HashMap<String, Object> hashmap = new HashMap<String, Object>();

public static String dictGet(String key){
    String val = (String) hashmap.get(key);
    return val;
}

public static int dictGet(String key, int pos){ 
    String val = (String) hashmap.get(key);
    byte[] bytes = val.getBytes(); 
    byte byt = bytes[pos /8];
    System.out.println("Byte : "+byt); 
    return (byt >> (pos % 8) ) & 1;

}
public static void dictSet(String key, String val){
    hashmap.put(key, val);
}
public static void dictSet(String key, int pos, byte bitval){
    String val = (String) hashmap.get(key);
    byte[] bytes = val.getBytes();
    byte byt = bytes[pos /8];

    if(bitval == 1){
        bytes[pos /8] = (byte) (bytes[pos /8]| (1 << (pos % 8)));
    }
    else if(bitval == 0){
        bytes[pos /8] = (byte) (bytes[pos /8] & ~(1 << (pos % 8)));
    }

    hashmap.put(key, new String(bytes));
}

我希望为每个这些函数实现 O(1)复杂度。但目前getBit()setBit()函数的时间复杂度为O(n)。 任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:2)

不,这不是O(1)的复杂性,它是O(n),其中n是字符串的长度。原因是您从bytes收到的getBytes()必须始终是副本;否则,String的不变性会受到损害。

这可以通过查看源代码来确认:getBytes调用encode,调用Arrays.copyOf

static byte[] encode(Charset cs, char[] ca, int off, int len) {
    StringEncoder se = new StringEncoder(cs, cs.name());
    char[] c = Arrays.copyOf(ca, ca.length); // <<=== Copying an array is O(n)
    return se.encode(c, off, len);
}

要获得O(1)摊销的复杂性(假设您要访问字符串的大多数位),您需要额外的存储空间 - HashMap<String,byte[]>这将是一个&#34;并行映射&#34;到原始哈希映射,存储&#34;缓存&#34; getBytes()次来电的值。首先寻找缓存的表示;如果不存在,请转到实际值,调用getBytes(),然后缓存结果。其余的代码将保持不变。

byte[] bytes = cache.get(key);
if (bytes == null) {
    String val = (String) hashmap.get(key);
    bytes = val.getBytes();
    cache.put(key, bytes);
}
byte byt = bytes[pos /8];
System.out.println("Byte : "+byt); 
return (byt >> (pos % 8) ) & 1;

请注意,cache的维护工作在您身上:每次修改hashmap时,您都需要从cache删除相应的密钥。

答案 1 :(得分:2)

这是非常低效的。 var myUser=$scope.AuthObj.$getAuth(); 将分配新数组(实际上不止一个),并在每次调用时将整个字符串编码到其中。这可能是此片段中最昂贵的操作。

此外,此代码混合了两个完全不同的表示。为了明确你的意图并避免错误,你应该坚持一个。如果要对字节进行操作,请在哈希映射中存储val.getBytes()。如果您想对字符或代码点进行操作,请使用charAtcodePointAt。如果您需要在这些表示之间进行转换,请在初始化期间执行一次。

另请注意,getBytes使用平台的默认字符集对字符串进行编码。如果使用UTF-16,这很可能不是你想要的,你的代码也会破坏。

以下是使用byte[]的示例,请注意,在Java StringBuilder中有16位且此代码使用了整个范围:

char

答案 2 :(得分:0)

我知道这与您的答案无关,但如果您使用的是Java,则应使用泛型类型,以便不需要强制转换。

回答你的问题,String.getBytes()的复杂性取决于String的长度。以这种方式思考,getBytes()方法将String中的每个字符转换为一个字节。因此,复杂度为O(L),其中L是字符串的长度。