Совсем недавно при работе с микросервисами я столкнулся с проблемой, когда мне нужно перебрать 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(), мне нужно быть внимательнее к переменным, уже определенным в области видимости ???
Моя единственная идея состоит в том, чтобы выявить различия, а не недооценивать или переоценивать возможности любого языка в конкретном случае!!!
Наслаждайтесь кодированием !!!