有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

数组在int[]中查找索引是否有更有效的Java8流方法?

基于BlackJack Question,我开始思考如何显示所有获胜的手。原来的问题实际上只是问了最多两个不大于21的数字。所以一种方法

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) { ... }

因此,根据输入数据,例如(仅在“座位”0、1、2使用3名“玩家”):

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

我预计产出大致如下:

Hands: [17, 15, 23] has winners at [0]
Hands: [23, 25, 22] has no winners
Hands: [18, 16, 18] has winners at [0, 2]
Hands: [16, 21, 20] has winners at [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,其中一个答案建议创建一个自定义收集器。不确定这是否是唯一的替代方法

感谢您提供的任何见解


共 (1) 个答案

  1. # 1 楼答案

    当你找到最大元素时,你错过了简单的解决方案。只需直接在数组的索引上创建一个流,而不需要中间列表:

    public static int[] blackjackByIteration(int[] hands) {
        OptionalInt oi = Arrays.stream(hands).filter(i -> i <= 21).max();
        if (oi.isPresent()) {
            int value = oi.getAsInt();
            return IntStream.range(0, hands.length).filter(i -> hands[i] == value).toArray();
        }
        return new int[0];
    }