2016-04-25 74 views
6

根據BlackJack Question,我想知道如何表示所有獲勝的牌。原來的問題跟它實際上,關於最大兩個數字並不比21更大所以像是否有更高效的Java 8 Stream方法來查找int []中的索引?

public int blackjack(int a, int b); 

但是,如果一個希望返回所有獲獎的手的方法(假設的位置輸入數組是在一個表中的座位),因此諸如簽名:

/** 
* returns an array indicate the index in the specified hands that 
* correspond to the winning locations. Will return an empty array if 
* there are no winners. The length of the returned array is how many 
* winning hands there were 
* @param hands The total for each hand, where the index is the seat 
* @return the index/"seat" where a winning hand was found; may return 
* an empty array 
*/ 
public int[] blackjack(int[] hands) { ... } 

所以基於輸入數據,如(只是使用3「運動員」在「座位」 0,1,2):

{17,15,23}
{23,25,22}​​
{18,16,18}
{16,21,20}

我期望沿着線輸出:

手: [17,15,23]具有[0]
手贏家:[23,25,22]無贏家
手:[18,16,18]具有[0,2]
手贏家: [16,21,20]獲得[1]

在過去,我會迭代hands[]數組,發現最大值爲< = 21,然後再次迭代查找每個等於最大值的索引。所以像這樣:

public static int[] blackjackByIteration(int[] hands) 
{ 
    int max = 0; 
    int numAtMax = 0; 
    for (int i = 0; i < hands.length; ++i) { 
     if (hands[i] <= 21 && hands[i] > max) { 
      max = hands[i]; 
      numAtMax = 1; 
     } 
     else if (hands[i] == max) { 
      ++numAtMax; 
     } 
    } 

    int[] winningSeats = new int[numAtMax]; 

    int loc = 0; 
    for (int i = 0; i < hands.length; ++i) { 
     if (hands[i] == max) { 
      winningSeats[loc++] = i; 
     } 
    } 

    return winningSeats; 
} 

但是,我想知道是否有一個更有效的方式來實現它通過流。我知道using Lambdas is not the solution to all problems。我相信,如果我的閱讀正確,那麼直接找到int[]陣列的索引是不可能的,因此該方法必須依靠使用List<Integer>,如question referenced above中所建議的那樣。

我做了一個初步的解決方案,使用Streams,但想知道是否有更有效的方法。我完全承認我對流的理解是有限的。

public static int[] blackjackByStreams(int[] hands) 
{ 
    // set to an empty array; no winners in this hand 
    int[] winningSeats = new int[0]; 

    // get the maximum that is <= 21 
    OptionalInt oi = Arrays.stream(hands).filter(tot -> tot <= 21).max(); 

    // if there are any hands that are <= 21 
    if (oi.isPresent()) { 
     // have to make a list (?) 
     List<Integer> list = Arrays.stream(hands) 
            .boxed() 
            .collect(Collectors.toList()); 

     // find the location(s) in the list 
     winningSeats = IntStream.range(0, list.size()) 
         .filter(i -> list.get(i) == oi.getAsInt()) 
         .toArray(); 
    } 

    return winningSeats; 
} 

這兩種方法返回相同的數據,所以它不是功能本身的問題。相反,有沒有辦法使blackjackByStreams更好?特別是,有沒有辦法消除List<Integer> list的創建?

編輯:我沒看過this question here,其中一個答案建議創建一個自定義收集器。不知道這是否是唯一的替代方法。

謝謝你提供任何見解。

+0

流通常不會提高效率。流通常不會比通常寫出的同一個程序更快,而且速度通常更慢。他們只是一個圖書館,他們不是魔術。您的初始代碼至少會更快,速度可能更快。 –

回答

4

當您找到最大元素時,您錯過了簡單的解決方案。只需直接在陣列的索引上創建一個流,而不是直接創建中間列表:

+0

我以爲我曾嘗試過,並收到錯誤,但在考慮它可能嘗試使用'Arrays.stream(手)...'而不是'IntStream.range(0,hands.length)...'。該方法的簡潔性大大提高! – KevinO

+1

@Holger不一定,數組可能具有大於21的所有值,因此OptionalInt將爲空。不幸的是,雖然'OptionalInt'上沒有'mapToObj',否則我們可以有'oi.mapToObj(...)。orElseGet(() - > new int [0])' – Tunaki

+1

確實,這很複雜。我應該再喝一杯咖啡......你可以做什麼來避免if是'int value = oi.orElse(21);'並且繼續第二個流操作,當沒有匹配時它將產生一個空數組。我仍然認爲,應該有一些更容易... – Holger

相關問題