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

Позвольте мне дать четкое представление о том, как выглядит проблема -

Ява:

Существует 2 списка, каждый элемент которых представляет собой кортеж/пару, содержащую ключ и значения. Ключ всех элементов в первом списке — «A», а во втором списке — «B». Теперь создайте окончательный список таким образом, чтобы, если два списка содержат какие-либо общие значения, запись должна была быть из первого списка с ключом «A», а затем добавить все непересекающиеся пары ключ-значение из обоих списков.

List<Map.Entry<String, String>> mainList = new ArrayList<>();
    List<Map.Entry<String, String>> finalList = new ArrayList<>();

    mainList.add(new AbstractMap.SimpleEntry<>("A","1"));
    mainList.add(new AbstractMap.SimpleEntry<>("A", "2"));

    mainList.add(new AbstractMap.SimpleEntry<>("B","2"));
    mainList.add(new AbstractMap.SimpleEntry<>("B","4"));

    List<String> list1 = mainList.stream()
            .filter(tuple1 -> tuple1.getKey().contains("A"))
            .map(tuple6 -> tuple6.getValue())
            .collect(Collectors.toList());
    
    List<String> list2 = mainList.stream()
            .filter(str -> str.getKey().contains("B"))
            .map(tuple1 -> tuple1.getValue())
            .collect(Collectors.toList());

    list1.retainAll(list2);

if(!list1.isEmpty())
{
    for(Map.Entry<String,String> entryWithIndexName : mainList)
    {
        String indexName = entryWithIndexName.getKey();
        String value = entryWithIndexName.getValue();
         Boolean isCommon = list1.contains(value);

        if(isCommon )
        {
            if(indexName.equalsIgnoreCase("A")) {
                finalList.add(new AbstractMap.SimpleEntry<>(indexName,value));
            }
        }
        else if(!isCommon)
        {
            finalList.add(new AbstractMap.SimpleEntry<>(indexName,value));
        }
    }
}
else
{
   finalList = mainList;
}

finalList содержит записи ("A","1'), ("A"",2') ,("B","4'). т.е. для общего значения «2» запись производится из 1-го списка, ключ которого «А».

Ясно, что мы могли видеть 40 строк кода, несмотря на использование потоков Java. Обратите внимание на сложность добавления кортежа в качестве записи в коллекцию. retainAll изменяет существующую коллекцию. Давайте посмотрим на стиль кодирования Scala -

val mainlist = List(("A", 1), ("A", 4), ("B", 5), ("B", 3))
val list1 = mainlist.filter{case(key, value) => key.equalsIgnoreCase("A")}
val list2 = mainlist.filter{case(key, value) => key.equalsIgnoreCase("B")}
val intersectList = list1.map(_._2).intersect(list2.map(_._2))
val finalList= mainlist.map{case(key,value) => if(intersectList.contains(value) && key.equalsIgnoreCase("A")) (key,value) else if(!intersectList.contains(value)) (key,value) else (null,null)}.filterNot{case(key, value) => value == null}

Вряд ли 10 строк кода !!!! Нет необходимости обрабатывать условие пустого списка !list1.isEmpty(), как в Java, или исключения нулевого указателя. Вот также одно из больших отличий в ОБЪЕМЕ переменных!!

Пример Скала:

def main(args:Array[String]): Unit =
{
  val x =10
  (11 to 20).foreach{x => println(x)}

  println("Global x: " + x)
}

Приведенный выше код работает отлично. Хотя мы определили переменную "x" внутри функции карты, ее область действия является локальной, и переменная умирает после завершения блока итераций. Следовательно, результатом вышеуказанной программы будет -

11
12
13
14
15
16
17
18
19
20
Global x: 10

Вот как работает область видимости в случае использования Javastreams:

public static void main(String[] args)
{
    String str = "hello";
    List<String> mainList = new ArrayList<>();
    mainList.add("hi");
    mainList.add("boy");
    mainList.add("good");
    mainList.add("bad");

    mainList.stream().map(ele ->
    {
        System.out.println("Different variable name: " + ele);
        return ele;
    }).collect(Collectors.toList());


    mainList.stream().map(str ->
    {
        System.out.println("Different variable name: " + str);
        return str;
    }).collect(Collectors.toList());

}

Первая операция map работает нормально, тогда как в случае операции второго потока она жалуется на использование str, заявляя, что "Переменная str уже находится в области действия". Я подумал, что если я собираюсь писать код с использованием streams(), мне нужно быть внимательнее к переменным, уже определенным в области видимости ???

Моя единственная идея состоит в том, чтобы выявить различия, а не недооценивать или переоценивать возможности любого языка в конкретном случае!!!

Наслаждайтесь кодированием !!!