简体   繁体   English

在Swift 3中实现Java String的hashCode()方法

[英]Implementing Java String's hashCode() method in Swift 3

I am creating an iOS version of an existing Android app. 我正在创建现有Android应用的iOS版本。 On the Android side, hashCode() of a String (username) is sent to the server and based on that hash, a JSON object is returned. 在Android端,String(用户名)的hashCode()被发送到服务器,并且基于该哈希,返回JSON对象。

On Swift, I tried hash and hashValue properties but both of them produces values that are different from their Android counterpart. 在Swift上,我尝试了hash和hashValue属性,但是它们都产生了与Android对应的值不同的值。

So I decided to write my own implementation based on Java's implementation: 所以我决定根据Java的实现编写自己的实现:

int h = hash;
if (h == 0 && value.length > 0) {
  char val[] = value;
  for (int i = 0; i < value.length; i++) {
    h = 31 * h + val[i];
  }
  hash = h;
}
return h;

But when I write the above implementation in Swift, I get overflow crash. 但是当我在Swift中编写上面的实现时,我会遇到溢出崩溃。 Can anybody help me here? 有人可以帮我吗?

Thanks in advance. 提前致谢。

Here is the Swift implementation: 这是Swift实现:

I first had to write a Character extension that would return Ascii value of the character: 我首先必须编写一个Character扩展,它将返回字符的Ascii值:

extension Character {
    var asciiValue: UInt32? {
        return String(self).unicodeScalars.filter{$0.isASCII}.first?.value
    }
}

Then I created a String extension with: 1. a property that returns Ascii values of each character in the String. 然后我创建了一个String扩展,其中包含:1。一个返回String中每个字符的Ascii值的属性。 2. a hash method to return the hash (copying the Java code) 2.一个返回哈希的哈希方法(复制Java代码)

extension String {
    var asciiArray: [UInt32] {
        return unicodeScalars.filter{$0.isASCII}.map{$0.value}
    }
    func myHash() -> Int {
        var h = 0 as Int!
        for i in 0..<asciiArray.count {
            h = 31*h! + Int(array[i])
        }
        return h!
    }
}

As the post is still missing an answer, here is the working code: 由于帖子仍然没有答案,这里是工作代码:

1) Write an extension for Characters, to map their ascii representation to an int - we need UInt32, as Java uses for the hashing a 32 bit system, not 64 bit. 1)为Characters编写扩展,将其ascii表示映射到int - 我们需要UInt32,因为Java用于散列32位系统,而不是64位。

2) Make sure our represented string does ONLY contain characters, which are mappable to ASCII 2)确保我们表示的字符串仅包含可以映射到ASCII的字符

3) Now perform the mentioned hashing function 3)现在执行上面提到的散列函数

int h = 0;
if (h == 0 && value.length > 0) {
  char val[] = value;
  for (int i = 0; i < value.length; i++) {
    h = 31 * h + val[i];
  }
  hash = h;
}
return h;

So, we will get the following code snippet, which could be used in your projects. 因此,我们将获得以下代码片段,可以在您的项目中使用。

// 1) Here is our Character extension
extension Character {
    var asciiValue: UInt32? {
        return String(self).unicodeScalars.filter{$0.isASCII}.first?.value
    }
}

extension String {
    // 2) ascii array to map our string
    var asciiArray: [UInt32] {
        return unicodeScalars.filter{$0.isASCII}.map{$0.value}
    }

    // this is our hashCode function, which produces equal output to the Java or Android hash function
    func hashCode() -> Int32 {
        var h : Int32 = 0
        for i in self.asciiArray {
            h = 31 &* h &+ Int32(i) // Be aware of overflow operators, 
        }
        return h
    }
}

By default, swift throws an exception on integer overflow (unlike C or the standard Java integer operations). 默认情况下,swift会在整数溢出时抛出异常(与C或标准Java整数操作不同)。 In order to preclude throwing the exception you have to use the special functions provided for that, like 'addWithOverflow'. 为了排除抛出异常,你必须使用为其提供的特殊函数,比如'addWithOverflow'。

Alternatively you can build using the 或者你可以使用
-Ounchecked flag -Ounchecked标志

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM