Java 8 потоков, как писать если еще внутри для l oop? - PullRequest
0 голосов
/ 10 июля 2020

У меня на l oop ниже. Я хочу преобразовать этот метод с помощью потоков.

public List<BigDecimal> func() {
    List<BigDecimal> list= new ArrayList<>();
    try {
        for (Item item : getList()) {
            if(!item.getDescr().trim().isEmpty()) {
                String[] descriptionList = item.getDescr().trim().split(";");
                if(descriptionList.length == 2 && isCurrentParameterActive(descriptionList[1]) ) {
                    list.add(new BigDecimal(item.getCode().trim()));
                }
            } else {
                list.add(new BigDecimal(item.getCode().trim()));
            }
        }
    } catch (Exception e) {
        //Do Nothing.
    }
    return list;
}

Я переписываю этот метод двумя разными способами.

Первый:

public List<BigDecimal> func() {
    List<BigDecimal> list= new ArrayList<>();
    Item[] items = null;
    try {
        items = getList();
    } catch (Exception e) {
        e.printStackTrace();
    }

    Arrays.stream(items).forEach(item -> {
        if(!item.getDescr().trim().isEmpty()){
            if(item.getDescr().trim().split(";").length==2 && isCurrentParameterActive( item.getDescr().trim().split(";")[1])){
            list.add(new BigDecimal(item.getCode().trim()));
        } else{
            list.add(new BigDecimal(item.getCode().trim()));
        }
    });

    return list;
}

Второй:

public List<BigDecimal> func() {
    List<BigDecimal> list = new ArrayList<>();
    Item[] items = null;
    try {
        items = getList();
    } catch (Exception e) {
        e.printStackTrace();
    }

    Arrays.stream(items).filter(item -> !item.getDescr().trim().isEmpty()).filter(item -> item.getDescr().trim().split(";").length ==2).
            filter(item -> isCurrentParameterActive(item.getDescr().trim().split(";")[1])).map(item -> list.add(new BigDecimal(item.getCode().trim())));


    Arrays.stream(items).filter(item -> item.getDescr().trim().isEmpty()).map(item -> list.add(new BigDecimal(item.getCode().trim())));

    return list;
}

Не уверен, верны они или нет. Но если они даже верны, я хочу другое. В первом преобразованном методе все еще есть блок if-else. Я не хочу сохранять блок if else в новом коде. Во втором преобразованном методе я дважды выполнял потоковые операции из-за блока if else.

Следовательно, я хочу преобразовать самую верхнюю функцию без блока if-else и с использованием одной цепочки потоковых операций. Не могли бы вы помочь мне? Я новичок в java8.

1 Ответ

0 голосов
/ 10 июля 2020

Вы можете немного упростить свой код, осознав, что вам не нужна сложная конструкция if-else.

Вы либо добавляете в свой список, если item.getDescr().trim().isEmpty() пуст, либо если второй параметр передает isCurrentParameterActive тест. Обратите внимание на либо - либо в предложении выше.

Вы можете упростить этот тест до

Predicate<Item> isActive = item -> {
    String[] parts;
    return item.getDescr().trim().isEmpty() 
            || ((parts = item.getDescr().trim().split(";")).length == 2
            && isCurrentParameterActive(parts[1]));
};

Обратите внимание, что вы также можете избежать выделения массива, просто проверив, присутствует ли ; в строке (через String#indexOf()), но только один ;, и вы можете получить некоторую микрооптимизацию, только обрезав описание один раз, как @Holger упомянул в комментарии. Собирая все это вместе, вы получаете:

Predicate<Item> isActive = item -> {
    var description = item.getDescr().trim();
    int partition;
    return description.isEmpty() 
            || ((partition = description.indexOf(";")) > 0 
                && description.indexOf(';', partition) < 0
                && isCurrentParameterActive(description.substring(partition)));
};

После этого вы можете просто отфильтровать все допустимые элементы из потока, а затем сопоставить их один раз с BigDecimal и собрать в список:

Arrays.stream(getList())
    .filter(isActive)
    .map(item -> new BigDecimal(item.getCode().trim()))
    .collect(Collectors.toList());

Объединение всего этого дает:

    public List<BigDecimal> func() {
        Predicate<Item> isActive = item -> {
            var description = item.getDescr().trim();
            int partition;
            return description.isEmpty() 
                || ((partition = description.indexOf(";")) > 0 
                    && description.indexOf(';', partition) < 0
                    && isCurrentParameterActive(description.substring(partition)));
        };
        
                
        return Arrays.stream(getList())
                .filter(isActive)
                .map(item -> new BigDecimal(item.getCode().trim()))
                .collect(Collectors.toList());  
    }

Кроме того, было бы разумно изменить getList(), чтобы фактически вернуть список, который может быть пустым (используйте Collections.emptyList() ).

...