[java]for-loopとStreamforEachの違いは何ですか?

28981 ワード

  • foreach巡回期間中断不可
  • for Each同時性
  • が必要

    概要


    個人的には、StreamのforEachが最近流行しており、コード量も相対的に少なく、アルゴリズムを解く際によく使われています.
    JavaScriptでforEachを使っているので、あまり問題ないと思います.
    そんなことはできないと思います.
    for loopとStream forEachの違いは、
  • foreach巡回期間中断不可
  • for Each同時性
  • が必要

    1.foreachツアーで中断不可


    1)問題


    たとえば、指定した配列でtargetに一致する要素を検索しています.
  • 1)要素がある場合は、その要素
  • を返します.
  • 2)要素-1なしで
  • を返します.

    2)コード


    forEach内部でbreakとreturnを使用すると、エラーが発生します.
    import java.util.Arrays;
    import java.util.concurrent.atomic.AtomicInteger;
    
    class Main {
        public static void main(String[] args) {
    
            // 주어진 배열에서 1) target이 있으면 target을 2) 없으면 -1을 반환합니다.
            int[] l = {0, 1, 2, 3, 4, 5};
            int target = 3;
    
            System.out.println("for-loop 결과: " + forLoop(target, l)); // for-loop 결과: 3
            System.out.println("forEach 결과: " + forEach(target, l)); // forEach 결과: 3
        }
    
        public static int forLoop(int target, int[] l) {
            // 주어진 배열을 순회합니다.
            for(int i=0; i<l.length; i++) {
                if(l[i] == target) {
                    // 타켓을 찾으면 반복문을 중단하고, 값을 바로 반환합니다.
                    return l[i];
                }
            }
            return -1;
        }
    
        public static int forEach(int target, int[] l) {
            // 멀티쓰레드 환경에서 동시성을 보장하기 위해 Atomic 변수를 사용합니다.
            AtomicInteger i = new AtomicInteger(-1);
            Arrays.stream(l).forEach(x -> {
                if(x == target) {
                    i.set(target);
                    // 타켓을 찾아도 forEach를 중단할 수 없습니다.
                    // return x;
                    // break;
                }
            });
            return i.get();
        }
    }

    2.forEach同期が必要


    1)問題


    接話ゲームをしていますが、答えを間違えるとそのまま이전 단어와, 현재 단어に戻ります.

    2)コード


    forEach内部に同期性はありません.外部変数を変更しようとするとエラーが発生します.
    この場合、原子変数が使用されます.原子はJavaマルチスレッド環境で同期を確保するために使用される変数であり、同期ではなくCAS(Compare and Swap)アルゴリズムを使用します.
    import java.util.Arrays;
    import java.util.concurrent.atomic.AtomicReference;
    
    class Main {
        public static void main(String[] args) {
    
            String[] words = {"apple", "elephant", "tree", "banana", "airplane"};
    
            System.out.println("for문 결과: " + forLoop(words)); // for문 결과: prev: tree cur: banana
            System.out.println("forEach 결과: " + forEach(words)); // forEach 결과: prev: tree cur: banana
        }
    
        public static String forLoop(String[] words) {
            String prev = "";
            for(String cur: words) {
                if(!prev.equals("") && prev.charAt(prev.length()-1) != cur.charAt(0)) {
                    return "prev: " + prev + " cur: " + cur;
                }
    
                prev = cur;
            }
            return "None";
        }
    
        public static String forEach(String[] words) {
            // 동시성을 보장하기 위해 atomic 변수를 사용합니다.
            AtomicReference<String> prev = new AtomicReference<>();
            AtomicReference<String> res = new AtomicReference<>();
    
            Arrays.stream(words).forEach(cur -> {
                if(!prev.toString().equals("") && prev.toString().charAt(prev.toString().length()-1) != cur.charAt(0)) {
                    res.set("prev: " + prev + " cur: " + cur);
                }
    
                prev.set(cur);
            });
            return res.toString();
        }
    }

    3.原子変数を使わずにforeachで変更できますか?


    次の2種類があります.
  • マッピング、set、listの
  • アレイ要素にインデックスでアクセスした場合:
  • import java.util.*;
    import java.util.concurrent.atomic.AtomicInteger;
    
    class Main {
        public static void main(String[] args) {
            // 1. 배열
            String[] words = {"apple", "elephant", "tree", "tree"};
    
            // 2. 컨테이너
            Map<String, Integer> m = new HashMap<>();
            Set<String> s = new HashSet<>();
            List<String> l = new ArrayList<>();
            String[] a = new String[words.length];
    
            AtomicInteger i = new AtomicInteger(0);
            Arrays.stream(words).forEach(x -> {
                // 1. map, set, list 에 넣는 경우
                m.put(x, m.getOrDefault(x, 0) + 1);
                s.add(x);
                l.add(x);
                
                // 2. 배열 요소에 인덱스로 접근하는 경우
                a[i.get()] = x;
                i.set(i.get() + 1);
            });
    
            m.forEach((key, value) -> System.out.println(key + " " + value));
            s.forEach(System.out::println);
            l.forEach(System.out::println);
            Arrays.stream(a).forEach(System.out::println);
        }
    }