2011-07-12 94 views
1

我想將信息存儲在緩存在內存中的java集合中。Java集合使用金額範圍

我有以下表

低於$ -1 - (存儲一些數據)

$ 1 $ 115,000個 - (存儲一些不同的數據)

$一十一萬五千〇一到$ 345,000 - (存儲一些不同的數據) (存放一些不同的數據)

$五八〇〇〇一以上 - -

$三四五零零一到580000(存儲一些不同的數據)

我想有一筆錢傳入一個函數。然後,我需要確定通過金錢匯入的金額範圍,以便我可以檢索其數據。例如,通過了127,000美元的金額。我需要使用上表中的第三行數據,因爲127,000美元在115,000美元和345,000美元之間。

我真的很感謝任何關於如何最佳設計的建議。

在此先感謝 道格

+0

給它一個鏡頭,回來什麼讓你。第1步 - 寫一個函數,接受一個數字,並給出一個範圍列表,確定數字落入的範圍。 –

回答

1

這是一個基本的工作示例。當然,你可能想要使用除MAX_VALUE和MIN_VALUE以外的其他東西作爲外邊界,並且你可能需要浮點數而不是整數。一個完整的實施將可能有CurrencyRange作爲一個界面,在這裏你可以有不同的實現,爲「1少於$」和「超過$ 580,000」的情況:

private static final List<CurrencyRange> ranges = Arrays.asList(
     new CurrencyRange(Integer.MIN_VALUE, 0, "some data"), 
     new CurrencyRange(1, 115000, "some data"), 
     new CurrencyRange(115001, 345000, "some data"), 
     new CurrencyRange(345001, 580000, "some data"), 
     new CurrencyRange(580001, Integer.MAX_VALUE, "some data") 
); 

public String determineDataByAmount(int amount) { 
    for (CurrencyRange range : ranges) { 
     if (range.contains(amount)) { 
      return range.getData(); 
     } 
    } 
    throw new IllegalStateException(
     "No suitable range found for amount: " + amount); 
} 

class CurrencyRange { 
    private int lowerLimit; 
    private int upperLimit; 
    private String data; 

    public CurrencyRange(int lowerLimit, int upperLimit, String data) { 
     this.lowerLimit = lowerLimit; 
     this.upperLimit = upperLimit; 
     this.data = data; 
    } 

    public boolean contains(int amount) { 
     return amount >= lowerLimit && amount <= upperLimit; 
    } 

    public String getData() { 
     return data; 
    } 
} 
1

條件判斷最適合。

function processMoney(int amount) { 
    if(amount > 580000) { 
     //do stuff 
    else if (amount > 345000) { 
     // do other stuff 
    } 
} 

+0

+1:恕我直言,這是最簡單的。 –

+0

我選擇了另一個,因爲它適合我們的情況。我們需要一個能夠適應不同情況的課程。我沒有使用他的確切代碼。 – Doug

0
public void function(int money) 
{ 
    if(money <= 1) //store some data 
    if(money >= 2 && money <= 115000) // Store some different data 
    if(money >= 115001 && money <= 345000) //Store some different data 
    if(money >= 345001 && money <= 580000) //Store some different data 
    if(money >= 580001) // Store some different data 

} 
+0

使用'else'可避免檢查範圍的開始和結束。另外想象一下,如果他爲金錢類型改變了一倍。 ;) –

0

在編碼端,這很容易。使用polymorphisim爲每個金額擁有不同的對象。

我收集的是,您還需要將其堅持到數據庫。雖然你沒有確切地說過,但大量使用諸如「表格」「數據」和「行」之類的詞語表明你關心的是數據庫存儲。要在數據庫中保留多態數據,只有幾個選項:

  1. 單表繼承 - 使用一個表來存儲多態層次結構中的所有類。
  2. 混凝土表繼承 - 對每個具體的子類使用一個表。
  3. 類表繼承 - 使用一個表作爲公共超類,每個子類使用一個表(具體或以其他方式)存儲在面向對象層次結構中定義的字段。

#1的優點是你只有一張表進行搜索,缺點是大部分表格都是變體數據的大塊。通常,具有「變體」部分的字段成爲存儲在一行中的XML文檔。無論哪種情況,如果要搜索不變量(總是存在)字段,這很容易;但是,如果變體字段要被搜索,則變得困難。

#2的優點是數據庫查詢使用標準SQL工具很容易。缺點是你必須採取特別的預防措施,不要在表中集合中存儲兩次相同的不變鍵,因爲這可能是說帳戶#5既是$ 5帳戶又是$ 50,000帳戶。

#3的優勢在於數據庫結構模仿類的層次結構,它可以緩解#2中的關鍵衝突問題,但仍然提供比#1更好的SQL查詢。缺點是要獲得任何單個對象,您必須通過外鍵執行連接(性能命中)。

總之,沒有銀子彈。但是,也許你並不是真的指數據庫表,在這種情況下,這不是問題。

1

使用二進制搜索來提高性能時:

private List<Double> ranges = Arrays.asList(1.0, 115000.0, 345000.0, 580000.0); 

private int findRange(double amount) { 
    final int idx = Collections.binarySearch(ranges, amount); 
    return idx >= 0 ? idx : -idx - 1; 
} 

和測試:

public class RangeTest { 

    @Test 
    public void shouldReturnIndex() throws Exception { 
     assertThat(findRange(0.5)).isEqualTo(0); 
     assertThat(findRange(1.0)).isEqualTo(0); 
     assertThat(findRange(1.01)).isEqualTo(1); 

     assertThat(findRange(114000.0)).isEqualTo(1); 
     assertThat(findRange(115000.0)).isEqualTo(1); 
     assertThat(findRange(115001.0)).isEqualTo(2); 

     assertThat(findRange(581000.0)).isEqualTo(4); 
    } 


} 

幾點注意事項:

    但它
  • 二進制搜索似乎是在您的情況矯枉過正,實際上是最簡單的實現,沒有任何顯式循環和任何定製邏輯
  • findRange()收益範圍你掉進指數(範圍的數量等於步數+ 1)
  • 你應該絕對使用BigDecimal,我以前double只是打一個比方簡單
  • 真正測試應該更短和更具描述性
1

一個你能處理這個方法是用NavigableSet

NavigableSet<Integer> cutoffs = new TreeSet<Integer>(); 
cutoffs.addAll(Arrays.asList(Integer.MIN_VALUE, 0, 150000, 345000, 580000)); 

... 

public void something(int amount) { 
    switch (cutoffs.lower(amount)) { 
    case Integer.MIN_VALUE: 
     // below 1 
    case 0: 
     // 1 to 150000 
    case 150000: 
     // etc 
    case 345000: 
     // etc 
    default: 
     // etc 
    } 
} 

這可能比只是做了平if/else(前提是你只創建cutoffs設置一次,並用此方法很多),但對於這樣一個簡單的例子,像你多一點效率,更簡單的東西如果不是更好,也可以。