J'ai le code suivant:
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
List<Long> newList = list.stream().map(i -> i * 2.5)
.mapToLong(Double::doubleToRawLongBits)
.collect(Collectors.toList());
Ce code ne fonctionne pas et l'erreur de compilation est:
méthode
collect
dans l'interfaceJava.util.stream.LongStream
ne peut pas être appliqué à des types donnés;
obligatoire:Java.util.function.Supplier<R>,Java.util.function.ObjLongConsumer<R>,Java.util.function.BiConsumer<R,R>
a trouvé:Java.util.stream.Collector<Java.lang.Object,capture#1 of ?,Java.util.List<Java.lang.Object>>
raison: ne peut pas déduire les variables de typeR
(les listes d'arguments réelles et formelles diffèrent en longueur)
J'ai essayé de nombreuses utilisations des collecteurs mais je ne peux toujours pas le faire fonctionner. Qu'est-ce que je fais mal?
mapToLong
vous donne un LongStream
qui ne peut pas être collect
- ed par Collectors.toList
.
C'est parce que LongStream
est
Une séquence d'éléments primitifs à valeur longue
Nous ne pouvons pas avoir un List<long>
, nous avons besoin d'un List<Long>
. Par conséquent, pour pouvoir les collecter, nous devons d'abord mettre ces long
s primitifs dans des objets Long
:
list.stream().map(i -> i * 2.5)
.mapToLong(Double::doubleToRawLongBits)
.boxed() //< I added this line
.collect(Collectors.toList());
La méthode boxed
nous donne un Stream<Long>
que nous pouvons rassembler dans une liste.
Utiliser map
plutôt que mapToLong
, comme suggéré par Louis Wasserman , fonctionnera également car cela entraînera un Steam<Long>
où les valeurs sont automatiquement encadrées:
list.stream().map(i -> i * 2.5)
.map(Double::doubleToRawLongBits)
.collect(Collectors.toList());
Cela devrait se compiler si vous utilisez map
au lieu de mapToLong
. (Je ne sais pas ce que vous essayez de faire avec doubleToRawLongBits
est logique, mais cela compilera au moins.)
Je ne sais pas à quoi vous vous attendez, mais cela génère un List<Long>
.
public void test() {
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
List<Long> newList = list.stream()
// Times 1.5.
.map(i -> i * 2.5)
// Grab the long bits.
.mapToLong(Double::doubleToRawLongBits)
// Box them.
.boxed()
// Make a list.
.collect(Collectors.toList());
System.out.println(newList);
}
L'essence de ce problème est que la valeur de retour de la fonction mapToLong
est LongStream
interface. LongStream
n'a qu'une méthode
<R> R collect(Supplier<R> supplier,
ObjLongConsumer<R> accumulator,
BiConsumer<R, R> combiner);
Vous voudrez peut-être utiliser la méthode
<R, A> R collect(Collector<? super T, A, R> collector);
Vous pouvez trouver cette méthode dans la classe Java.util.stream.Stream .
LongStream
et Stream
n'ont pas de relation d'extension.
La raison pour laquelle vous souhaitez utiliser doubleToRawLongBits
n'est pas claire. Si votre problème est que la multiplication par 2.5
produit double
plutôt que long
, vous avez besoin d'un transtypage de type pour convertir la valeur, car doubleToRawLongBits
n'est pas la manière canonique de convertir double
en long
. Au lieu de cela, cette méthode renvoie la représentation IEEE 754 de la valeur qui n'est intéressante que dans des cas très spéciaux. Notez que vous pouvez effectuer la conversion directement dans la première opération map
:
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
List<Long> newList = list.stream().map(i -> (long)(i * 2.5))
.collect(Collectors.toList());
Cela s'applique même si vous voulez vraiment la représentation IEEE 754 des valeurs double
:
List<Long> newList = list.stream().map(i -> Double.doubleToRawLongBits(i * 2.5))
.collect(Collectors.toList());
Mais notez que si vous avez une liste temporaire dont le type correspond au type de résultat, vous pouvez effectuer l'opération sur place au lieu de créer deux listes (et en passant par l'API Stream
):
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
list.replaceAll(i -> (long)(i * 2.5));
encore une fois, la même chose s'applique même si vous voulez IEEE 754 bits:
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
list.replaceAll(i -> Double.doubleToRawLongBits(i * 2.5));
Si vous insistez pour utiliser l'API Stream
, vous pouvez utiliser le générateur plutôt qu'un ArrayList
pour les données source:
Stream.Builder<Long> b = Stream.builder();
b.add(4L);
b.add(92L);
b.add(100L);
List<Long> newList = b.build().map(i -> (long)(i * 2.5))
.collect(Collectors.toList());
newList.forEach(System.out::println);
HashMap<String, Map<String, Long>> map = new HashMap<>();
List<Entry<String, Map<String, Long>>> sortedList = map
.entrySet()
.stream()
.sorted((a, b) -> Long.compare(
a.getValue().values().stream().mapToLong(l -> l).sum(),
b.getValue().values().stream().mapToLong(l -> l).sum()))
.collect(Collectors.toList());