2015-06-11 2 views
12

У меня есть следующий код:Collect список Лонга из двойного потока в Java 8

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()); 

Этот код не работает и ошибка компиляции:

Error:(28, 96) java: method collect in interface java.util.stream.LongStream cannot be applied to given types; required: java.util.function.Supplier,java.util.function.ObjLongConsumer,java.util.function.BiConsumer found: java.util.stream.Collector> reason: cannot infer type-variable(s) R (actual and formal argument lists differ in length)

Я пробовал много использований Коллекционеров, но я все еще не могу заставить его работать. Что я делаю неправильно?

+1

Что именно вы думаете, что делает «Double.doubleToRawLongBits'? Я не думаю, что вы знаете, что он делает ... –

+0

Он становится DoubleStream после умножения на 2.5. – aldrael

+1

@aldrael: неверно. Он становится «Stream », что не то же самое. –

ответ

11

Это должно скомпилироваться, если вы используете map вместо mapToLong. (Я не уверен, что вы пытаетесь сделать с doubleToRawLongBits, имеет какой-то смысл, но это, по крайней мере, скомпилирует.)

+0

Дело в том, что я хочу получить Список , но используя только map() и collect(), я получаю Список . – aldrael

+1

@aldrael: no. Замена 'mapToLong' на' map' отлично работает. Просто попробуй. –

5

Не знаете, что вы ожидаете от ваших результатов, но это создает 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); 
} 
+3

'mapToLong (f) .boxed()' полностью эквивалентен 'map (f)'. –

1

Непонятно, почему вы хотите использовать doubleToRawLongBits. Если ваша проблема заключается в том, что умножение с 2.5 производит double, а не long, вам нужно, чтобы тип преобразования преобразовывал значение, так как doubleToRawLongBits не является каноническим способом преобразования double в long. Вместо этого этот метод возвращает представление IEEE 754 значения, которое интересно только в особых случаях. Обратите внимание, что вы можете выполнить преобразование прямо внутри первой 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()); 

Это относится даже если вы действительно хотите представление IEEE 754 double значений:

List<Long> newList = list.stream().map(i -> Double.doubleToRawLongBits(i * 2.5)) 
         .collect(Collectors.toList()); 

Но обратите внимание, что если у вас есть временный список, тип которого соответствует типу результата, вы можете выполнить операцию на месте вместо создания двух списков (и пройти через API Stream):

List<Long> list = new ArrayList<>(); 
list.add(4L); 
list.add(92L); 
list.add(100L); 
list.replaceAll(i -> (long)(i * 2.5)); 

снова, то же самое относится даже если вы хотите IEEE 754 бит:

List<Long> list = new ArrayList<>(); 
list.add(4L); 
list.add(92L); 
list.add(100L); 
list.replaceAll(i -> Double.doubleToRawLongBits(i * 2.5)); 

Если вы настаиваете на использовании Stream API, вы можете использовать строитель, а не ArrayList для исходных данных:

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); 
6

mapToLong дает вам LongStream, который не может быть collect -ed по Collectors.toList.

Это потому, что LongStream является

A sequence of primitive long-valued elements

Чтобы иметь возможность собрать их, нам сначала нужно боксировать эти примитивные long S в Long объектов:

list.stream().map(i -> i * 2.5) 
    .mapToLong(Double::doubleToRawLongBits) 
    .boxed()        //< I added this line 
    .collect(Collectors.toList()); 

Использование map, а не mapToLong, а предложенный Louis Wasserman, также будет работать, потому что это приведет к Steam<Long>, где значения автоматически помещаются в бокс:

list.stream().map(i -> i * 2.5) 
    .map(Double::doubleToRawLongBits) 
    .collect(Collectors.toList()); 
+0

Какой прекрасный ответ! Благодарю. –

+0

Это лучший ответ, потому что он помогает мне, как программисту, который новичок в Java 8, понять «_why_». Спасибо огромное! – Eddified