Sulla base di uno BlackJack Question, mi sono chiesto come indicare tutte le mani vincenti. La domanda iniziale semplicemente chiesto, in effetti, circa il massimo di due numeri non maggiori di 21. Quindi, un metodo comeC'è un approccio Java 8 Stream più efficiente per trovare l'indice in un [] int?
public int blackjack(int a, int b);
Tuttavia, se uno volesse restituire tutti delle mani vincenti (assumendo la posizione nella array di input era un posto ad un tavolo), quindi una firma come:
/**
* 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) { ... }
quindi in base ai dati di input come (usando solo 3 "giocatori" a "sedi" 0, 1, 2):
{17, 15, 23}
{23, 25, 22}
{18, 16, 18}
{16, 21, 20}
ci si aspetterebbe di uscita lungo le linee di:
mani: [17, 15, 23] ha vincitori [0]
mani: [23, 25, 22] non ha vincitori
mani: [18, 16, 18] ha vincitori [0, 2]
mani: [16, 21, 20] ha vinto a [1]
In passato, avrei ripetuto l'array hands[]
, trovato il massimo che era < = 21 e poi ripetuto di nuovo l'individuazione di ciascun indice uguale al massimo. Quindi qualcosa del genere:
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;
}
Tuttavia, mi chiedevo se esistesse un modo più efficiente di implementarlo tramite i flussi. Sono consapevole che using Lambdas is not the solution to all problems. Credo che, se ho letto correttamente, non è possibile trovare direttamente l'indice di un array int[]
, quindi l'approccio deve fare affidamento sull'uso di un List<Integer>
, come suggerito nello question referenced above.
Ho fatto una soluzione iniziale utilizzando Streams, ma mi chiedevo se esistesse un approccio più efficiente. Ammetto pienamente che la mia comprensione dei flussi è limitata.
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;
}
I due approcci restituiscono gli stessi dati, quindi non è una questione di funzionalità per sé. Piuttosto, c'è un modo per rendere il blackjackByStreams
migliore? Soprattutto, c'è un modo per eliminare la creazione del List<Integer> list
?
Modifica: ho letto this question here, in cui una risposta suggeriva la creazione di un raccoglitore personalizzato. Non sono sicuro se questo sarebbe l'unico approccio alternativo.
Grazie per aver fornito informazioni.
Gli stream non migliorano, in generale, l'efficienza. Gli stream non saranno generalmente più veloci e spesso più lenti dello stesso programma scritto normalmente. Sono solo una biblioteca, non sono magici. Il tuo codice iniziale sarà almeno altrettanto veloce e probabilmente più veloce. –