2008-12-20 113 views
10

什麼是Java中最簡單的方法來映射字符串(Java的String)至(正)整數(Java的int),使映射字符串到整數

  • 等於字符串映射平等的整數,和
  • 不同的字符串映射到不同的整數?

所以,與hashCode()類似,但需要不同的字符串來產生不同的整數。所以,從某種意義上說,它將是一個沒有碰撞可能性的hasCode()。

一個顯而易見的解決方案將維護映射表從字符串到整數, 和一個計數器,以保證新字符串被分配一個新的整數。我只是想知道 這個問題通常如何解決。 將它擴展到除字符串以外的其他對象也很有趣。

+0

我不知道爲什麼你想Integer通過toString()輕鬆地將字符串映射到字符串,反之亦然使用Integer.valueOf()所以有什麼意義? – cletus 2008-12-20 18:31:21

+1

@cletus:使用Integer.valueOf(),「Hello」不容易映射爲整數。 – 2008-12-20 18:32:29

+0

那麼測試問題的有效性部分呢?這個問題確實需要重申和/或澄清。它沒有任何意義。 – cletus 2008-12-20 18:35:40

回答

4

這是無法實現的,沒有任何限制,只是因爲有更多的可能的字符串比整數,所以最終你會用完數字。

解決方案只有在限制可用字符串的數量時纔有可能。然後你可以使用一個簡單的計數器。這裏有一個簡單的實現,其中可以使用全部(2^32 = 4294967296個不同的字符串)。別介意它使用大量的內存。

import java.util.HashMap; 
import java.util.Map; 

public class StringToInt { 

    private Map<String, Integer> map; 

    private int counter = Integer.MIN_VALUE; 

    public StringToInt() { 
     map = new HashMap<String, Integer>(); 
    } 

    public int toInt(String s) { 
     Integer i = map.get(s); 
     if (i == null) { 
      map.put(s, counter); 
      i = counter; 
      ++counter; 
     } 
     return i; 
    } 
} 
4

這不會是一個簡單或完整的解決方案。我們使用哈希函數,因爲有更多可能的字符串比int數更多。碰撞只是使用有限數量的位來表示整數的限制。

1

您可以使用地圖來指示哪些字符串已經分配給整數嗎?這就是「數據庫-y」解決方案,您可以在每個字符串中爲來自序列的「主鍵」分配一個序列。然後你把String和Integer對放到一個Map中,這樣你就可以再次查看它。如果你需要一個給定的Integer的字符串,你也可以把同一對放入一個Map中。

2

由於java中的字符串的長度是無限的,並且每個字符都有16位,並且整數有32位,所以如果字符串最多爲兩個字符,則只能生成字符串的唯一映射。但是你可以使用的BigInteger產生一個唯一的映射,喜歡的東西:

String s = "my string"; 
BigInteger bi = new BigInteger(s.getBytes()); 

反向映射:

String str = new String(bi.toByteArray()); 
3

我會嘗試通過引入對象拿着地圖和地圖做。將字符串添加到該對象(或者可能讓它們從所述對象創建)將爲它們分配一個整數值。爲已經註冊的字符串請求整數值將返回相同的值。

缺點:對於相同的字符串,不同的啓動會產生不同的整數,具體取決於順序,除非您以某種方式持續整個事情。另外,它不是很面向對象,需要一個特殊的對象來創建/註冊一個String。另外一方面:這與字符串內部化非常相似,並且容易理解。 (另外,你要求一種簡單而不優雅的方式。)

對於更一般的情況,你可以創建Object的高級子類,在那裏引入一個「integerize」方法並從中擴展每一個類。然而,我認爲這條道路會導致流淚。

0

如果按整數表示數據類型,那麼正如其他海報解釋的那樣,這是完全不可能的,因爲整數數據類型的大小是固定的,並且字符串是未綁定的。

但是,如果你只是一個正數,那麼理論上你應該能夠將字符串看作是一個「整數」,只需將它看作一個字節數組(以一致的編碼方式)即可。你也可以把它當作一個任意長度的整數數組,但是如果你可以這樣做,爲什麼不使用一個字符串呢? :)

執行說話,這通常是通過使用哈希代碼和簡單地檢查任何衝突「解決」,因爲有可能沒有任何衝突,並在碰撞的機會,它仍然工作時間不變。但是,如果這不適用,我不確定最好的解決方案是什麼。

有趣的問題。

4

在大多數hashcode()類型實現中,碰撞被接受爲不可避免的並且經過測試。

如果您絕對必須沒有碰撞,保證,您概述的解決方案將工作。

除此之外,還有加密散列函數,如MD5和SHA,其中衝突極不可能(儘管可以強制執行很多努力)。 Java密碼體系結構具有這些實現。這些方法可能比爲您的解決方案實現非常大的集合更好。它們也會在固定時間內執行,併爲相同的字符串提供相同的代碼,而不管字符串以何種順序添加。並且,它不需要存儲每個字符串。加密哈希結果可以被認爲是整數,但它們不適合java int - 你可以使用BigInteger來保存它們,正如另一個答案中的建議。順便說一句,如果你因爲碰撞'非常不可能'的想法而被推遲,那麼在你的計算機內存或硬盤上隨機翻轉並導致任何程序的行爲與你不同的可能性相似期望:-)

注意,在一些散列函數(例如MD5)中也存在一些理論上的弱點,但爲了您的目的可能無所謂,您可以使用最有效的這種函數 - 這些弱點僅與相關如果有人惡意試圖想出與另一個字符串具有相同代碼的字符串。

編輯:我只是注意到你的問題的標題,似乎你想要雙向映射,儘管你沒有在問題中說明這一點。它是(設計上)不可能從加密哈希到原始字符串。如果你真的需要這個,你必須將一個映射密鑰散列存儲回字符串。

1

正如您概述的那樣,解決衝突的散列表是一個標準解決方案。您也可以使用Bentley/Sedgewick風格的搜索特徵,在許多應用程序中,搜索特徵比散列更快。

如果您將'唯一指針'替換爲'唯一整數',您可以看到Dave Hanson's solution to this problem in C。這是一個相當不錯的抽象,因爲

  • 指針仍然可以用作C字符串。

  • 等號字符串散列到等號指針,所以strcmp可以免去有利於指針相等,並且指針可以用作其他散列表中的密鑰。

如果Java程序String對象提供測試對象的身份,那麼你可以在那裏玩同一遊戲。