2014-01-28 5 views
1

Рассмотрим следующий класс у меня в данный момент:Как использовать Stream <E> вместо Collection <E> или List <E>?

public interface Drawable { 
    public void compileProgram(); 

    public Program getProgram(); 

    public int getDataSize(); 

    public FloatBuffer putData(final FloatBuffer dataBuffer); 

    public int getDataMode(); 

    public static int countDataSize(final Collection<Drawable> drawables) { 
     return drawables.stream().mapToInt((drawable) -> drawable.getDataSize()).sum(); 
    } 

    public static FloatBuffer putAllData(final List<Drawable> drawables) { 
     FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(countDataSize(drawables) * 3); 
     drawables.stream().forEachOrdered((drawable) -> dataBuffer.put(drawable.putData(dataBuffer))); 
     return (FloatBuffer)dataBuffer.clear(); 
    } 
} 

Теперь посмотрим на countDataSize:

  • меня в качестве входных данных Collection<Drawable>, потому что я не забочусь о порядке, я просто хочу, чтобы подвести их размер.
  • Я использую drawables.stream(), что было бы излишним, если бы я прошел в аргументе Stream<Drawable>.

А рядом посмотрим на putAllData:

  • Как и поместить здесь у меня есть List<Drawable> drawables, как заказ на этот раз имеет значение.
  • Я использую drawables.stream() для доступа к ним, это происходит в порядке forEachOrdered().

Я wush использовать Stream<Drawable> в качестве входных данных, однако это проходит в Collection<Drawable> или List<Drawable> работать даже тогда? Если да, то как я могу гарантировать, что в первом случае заказ не имеет значения, а во втором случае это имеет значение?

+1

Боковой комментарий: 'drawables.stream(). MapToInt ((drawable) -> drawable.getDataSize()). Sum();' может быть написано 'drawables.stream(). MapToInt (Drawable :: getDataSize). sum(); ' – assylias

ответ

1

Я хотел бы использовать Stream<Drawable> в качестве входных данных, однако это проходит в Collection<Drawable> или List<Drawable> работать даже тогда?

Нет, потоки не являются частью иерархии классов Collection, так что если ваш метод ожидает Stream<e> он не может принять Collection/List<E>.

Также обратите внимание, что передача потоков вокруг не обязательно добавляет столько преимуществ в вашем случае, потому что потоки могут потребляться только один раз. Например, это не будет работать:

Stream<E> s = ...; 
putAllDate(s); 
countDataSize(s); //IllegalStateException 

Последнее утверждение вызвало бы java.lang.IllegalStateException: stream has already been operated upon or closed.

+0

Хорошо, это действительно имеет смысл, не считал это раньше. Любой подсказку, как это перевести в байт-код, потому что огромные штрафы за производительность не стоят потоков в этом случае? – skiwi

+0

@skiwi Я не измерил, но штраф за производительность, вероятно, минимален - в конце концов он собирается перебирать вашу коллекцию и добавлять ints, более или менее так же, как вы могли бы написать это как цикл. – assylias

+0

@skiwi Большое улучшение производительности придет с 'countDataSize', если у вас много (> 10000) элементов: напишите' drawables.parallelStream(). MapToInt (Drawable :: getDataSize) .sum(); 'для параллельного выполнения. –

Смежные вопросы