Как сравнить элементы списка, используя потоки? - PullRequest
3 голосов
/ 06 ноября 2019

Например, мне нужно перебрать пользовательский список List<Model> и сравнить элементы в нем. Так что с циклом for это будет выглядеть так

for(int i = 0; i < list.size()-1; i++) {
    for (int j = i + 1; j < list.size(); j++) {
        if (list.get(i).getSomeItem().equals(list.get(j).getSomeItem()){
                /*modify the list using*/
                list.get(j).setSomeOtherItem(list.get(i).getSomeItem()+list.get(j).getSomeItem());
        }
    }
}

Но как получить тот же результат с потоками или forEach()? Я пытаюсь сделать что-то вроде этого

for (Model i : list){
    for (Model j : list){
        if(i.getSomeItem.equals(j.getSomeItem()){
            /*same logic as in for loop*/
        }
    }
}

или этого

 List<StorageModel> newList = list.stream()
           .filter(item -> item.getSomeItem.equals...)

Так что проблема в том, что при forEach оба цикла начинаются с одного и того же элемента и сравнивают одинаковые элементы,С потоками я не знаю, как получить следующее значение. Есть ли способ сделать это?

Ответы [ 3 ]

1 голос
/ 06 ноября 2019

Очень важно понимать, что потоковый API, предоставляемый Java, является не просто API, но и другой парадигмой программирования. Когда вы используете потоки, вы должны принять эту парадигму. Вы указываете потокам, чего хотите достичь, а не как хотите этого достичь . И, как и во многих других случаях, использование потоков не всегда является лучшим решением. Иногда использование простых старых циклов foor делает код более легким для чтения и, вероятно, также более эффективным.

Использование потоков

Если вы хотите использовать потоки в этом примере, вы можете сделать нечто подобное, как показано ниже.

Насколько я могу судить, вы пытаетесь найти элементы, которые (по некоторым критериям) одинаковы. Другими словами, вы хотите сгруппировать элементы на основе значения свойства объекта Model.

Допустим, наш класс Model выглядит следующим образом:

public class Model {
    private int id;
    private String name;

    public Model(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

В приведенном ниже примере показано, как группировать элементы списка моделей на основе их названий.

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class CompareItems {

    public static void main(String[] args) {
        List<Model> items = Arrays.asList(
                new Model(1, "model_1"), new Model(2, "model_2"), new Model(3, "model_1"),
                new Model(4, "model_3"), new Model(5, "model_2"), new Model(6, "model_2"));

        Map<String, Set<Integer>> result = 
                items.stream()
                .collect(Collectors.groupingBy(Model::getName, Collectors.mapping(Model::getId, Collectors.toSet())));

        System.out.println(result);
    }
}

Когда вы печатаете объект result, вы получите следующее:

{model_1=[1, 3], model_3=[4], model_2=[2, 5, 6]}

В объекте result у вас есть имя модели и идентификаторы:все объекты модели с одинаковыми именами.

В зависимости от того, что вы хотите сделать, вы можете применить изменения к каждой группе, перебирая объект result.

0 голосов
/ 06 ноября 2019

Вы можете попробовать уменьшить метод в этом случае.

list.stream().reduce((Item a, Item b)->{
        if(a.equals(b)){
            a.setValue(a.getValue()+b.getValue());
        }
        return b;
    });
0 голосов
/ 06 ноября 2019

Если у вас есть два ArrayList A и B, вы можете получить

  • A + B с A.addAll (B)
  • A - B с A.removeAll (B)
  • A ∩ B с A.retainAll (B)
  • A ∪ B с копированием A для установки A 'затем A'.addAll (B)

ТогдаВы можете использовать потоки для обработки результата, если вам нужно. Однако получение желаемого подмножества, которое вас интересует (например, общие элементы или A ∩ B), на самом деле не то, что я хотел бы сделать с потоками.

...