Java에서 정규식(Regex)은 java.util.regex 패키지의 Pattern 및 Matcher 클래스를 사용하여 처리됩니다.

  • Pattern : 정규식 패턴을 정의하는 클래스
  • Matcher : 패턴과 문자열을 매칭하는 클래스
  • PatternSyntaxException : 정규식 구문 오류 예외

1. 정규식 기본 문법

패턴 설명 예제
 .  임의의 문자 (줄바꿈 제외) "a.c""abc", "a3c" 매칭
 ^  문자열의 시작 "^Hello""Hello world" 매칭
 $  문자열의 끝 "world$""Hello world" 매칭
 *  0개 이상 반복 "a*""", "a", "aaa"
 +  1개 이상 반복 "a+""a", "aaa" (빈 문자열 X)
 ?  0개 또는 1개 "a?""", "a"
{n} 정확히 n개 반복 "a{3}""aaa"
{n,} n개 이상 반복 "a{2,}""aa", "aaa", "aaaa"
{n,m} n개 이상 m개 이하 반복 "a{2,4}""aa", "aaa", "aaaa"
 []  문자 집합 (ex: [abc] → a 또는 b 또는 c) "[abc]""a", "b", "c"
[^] 제외 문자 (ex: [^abc] → a, b, c 제외) "[^abc]""d", "e" (a, b, c 제외)
() 그룹화 (ex: (abc)+ → abc 1번 이상 반복) "(abc)""abc"
\d 숫자 [0-9] "\d""1", "5", "9"
\D 숫자가 아닌 문자 [^0-9] "\D""a", "B", "@"
\w 알파벳 + 숫자 + _([a-zA-Z0-9_]) "\w""a", "Z", "9", "_"
\W \w가 아닌 문자 "\W""@", "#", " "
\s 공백 문자 (스페이스, 탭, 개행) "\s"" ", "\n", "\t"
\S 공백이 아닌 문자 "\S" "a", "1", "@"

2. 정규식 활용 예제

문자열이 특정 패턴과 일치하는지 확인

import java.util.regex.*;

public class RegexExample {
    public static void main(String[] args) {
        String pattern = "\\d{3}-\\d{4}-\\d{4}"; // 010-1234-5678 형식
        String input = "010-1234-5678";

        boolean isMatch = Pattern.matches(pattern, input);
        System.out.println("일치 여부: " + isMatch); // true
    }
}

 

패턴에 맞는 문자열 찾기 (find)

import java.util.regex.*;

public class RegexFindExample {
    public static void main(String[] args) {
        String text = "My phone number is 010-1234-5678.";
        String pattern = "\\d{3}-\\d{4}-\\d{4}";

        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(text);

	// find() : 패턴과 일치하는 부분을 찾음
        if (m.find()) {
        // group() : 매칭된 문자열 반환
            System.out.println("찾은 값: " + m.group()); // 010-1234-5678
        }
    }
}

 

여러 개의 패턴 찾기

import java.util.regex.*;

public class RegexMultipleMatch {
    public static void main(String[] args) {
        String text = "Emails: test@example.com, hello@domain.net";
        String pattern = "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}";

        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(text);

        while (m.find()) {
            System.out.println("이메일 찾음: " + m.group());
            // 이메일 찾음: test@example.com
            // 이메일 찾음: hello@domain.net
        }
    }
}

 

문자열을 정규식으로 분리 (split)

import java.util.regex.*;

public class RegexSplitExample {
    public static void main(String[] args) {
        String text = "apple,banana;grape orange";
        String[] result = text.split("[,; ]"); // 쉼표(,), 세미콜론(;), 공백( )으로 분리

        for (String word : result) {
            System.out.println(word);
        }
    }
}

 

출력 결과

apple
banana
grape
orange

 

문자열 치환 (replaceAll)

import java.util.regex.*;

public class RegexReplaceExample {
    public static void main(String[] args) {
        String text = "Hello 123, this is a test 456!";
        String result = text.replaceAll("\\d+", "[NUMBER]"); // 숫자 제거

        System.out.println(result); // Hello [NUMBER], this is a test [NUMBER]!
    }
}

3. 자주 쓰는 정규식 패턴

용도 정규식
이메일 검사 ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
전화번호 (010-1234-5678) ^010-\d{4}-\d{4}$
URL 검사 ^(https?
한글만 포함 ^[가-힣]+$
영문자만 포함 ^[a-zA-Z]+$
숫자만 포함 ^\d+$
비밀번호 (영문+숫자 조합, 8~16자) ^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,16}$

4. 정규식 플래그

Pattern.compile("pattern", Pattern.CASE_INSENSITIVE);
플래그 설명
Pattern.CASE_INSENSITIVE 대소문자 구분 안 함
Pattern.MULTILINE 여러 줄 모드 ( ^ 와  $ 가 줄마다 적용됨)
Pattern.DOTALL  . 이 개행 문자( \n ) 포함 모든 문자에 매칭됨
Pattern.UNICODE_CASE 유니코드 문자에 대해 대소문자 무시
Pattern.COMMENTS 공백과  이후 주석 무시

5. Stream과 정규식 활용

import java.util.regex.Pattern;

public class StreamRegex {
    public static void main(String[] args) {
        String text = "Java 8, Java 11, Java 17";
        Pattern.compile("\\d+")
                .matcher(text)
                .results()
                .map(m -> "버전: " + m.group())
                .forEach(System.out::println);
    }
}

 

출력 결과

버전: 8
버전: 11
버전: 17

 

Java에서 정규식을 활용하면 문자열 검사, 파싱, 치환 등의 작업을 효과적으로 수행할 수 있습니다. 

 

Java Stream API에서 collect() 메서드는 스트림의 요소들을 컬렉션으로 집계하거나, 다양한 방식으로 결과를 처리할 때 사용됩니다. 주로 Collectors 유틸리티 클래스와 함께 사용되며, 리스트 변환, 그룹화, 조인, 맵핑 등의 기능을 제공합니다. 가장 많이 사용되는 컬렉는 Collectors.toList(), Collectors.toSet(), Collectors.toMap() 등이 있습니다.


주요 Collectors 메소드

1. 리스트(List)나 집합(Set)으로 변환 - toList(), toSet(), toMap()

스트림 결과를 List, Set, Map 등으로 변환 할 수 있습니다.

import java.util.*;
import java.util.stream.Collectors;

public class CollectExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "Apple");

        // List로 수집
        List<String> fruitList = fruits.stream()
                .collect(Collectors.toList());
        System.out.println("List: " + fruitList);  // List: [Apple, Banana, Cherry, Apple]

        // Set으로 수집 (중복 제거)
        Set<String> fruitSet = fruits.stream()
                .collect(Collectors.toSet());
        System.out.println("Set: " + fruitSet);  // Set: [Apple, Cherry, Banana]
    }
}

 

스트림의 요소들을 Map으로 변환 하는 예제 입니다. Map은 키 중복시 에러가 발생합니다. 중복 발생 시 mergeFunction을 추가하여 해결 할 수 있습니다.

public class CollectExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "melon");
        
        // 과일 이름을 길이로 매핑하여 Map으로 변환(키값 중복시 에러)
        Map<String, Integer> fruitLengthMap = fruits.stream()
         .collect(Collectors.toMap(fruit -> fruit, String::length)); // 이름을 키, 길이를 값으로

        System.out.println("Map :" + fruitLengthMap); // Map :{Apple=5, Cherry=6, melon=5, Banana=6}
        
    }
}
class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name;
    }
}

public class CollectExample {
    public static void main(String[] args) {
    	List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 30),
                new Person("David", 25)
        );

    	Map<String, Integer> nameToAgeMap = people.stream()
    	        .collect(Collectors.toMap(person -> person.name, person -> person.age));

    	System.out.println(nameToAgeMap); // {Alice=30, Bob=25, Charlie=30, David=25}
    	
    }
}

 

다음 예제는 mergeFunction을 추가하여 중복 문제를 해결 하는 예제입니다.

class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name;
    }
}

public class CollectExample {
    public static void main(String[] args) {
    	List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 30),
                new Person("Alice", 25)
        );

    	Map<Integer, String> ageToNames = people.stream()
    	        .collect(Collectors.toMap(
    	                person -> person.age,
    	                person -> person.name,
    	                (existing, newValue) -> existing + ", " + newValue // 중복 Key 처리
    	        ));

    	System.out.println(ageToNames); // {25=Bob, Alice, 30=Alice, Charlie}	
    }
}

 

아래와 같이 List -> Map -> LinkedHashMap로 결과 값을 변환 할 수도 있다.

class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name;
    }
}

public class CollectExample {
    public static void main(String[] args) {
    	List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 30),
                new Person("David", 25)
        );

    	Map<String, Integer> nameToAgeMap = people.stream()
    	        .collect(Collectors.toMap(person -> person.name, person -> person.age));
    	
    	LinkedHashMap<String, Integer> changeLinkedHashMap = nameToAgeMap.entrySet().stream()
                .sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey()))
                .collect(LinkedHashMap::new, (m, e) -> m.put(e.getKey(), e.getValue()), Map::putAll);

    	System.out.println(changeLinkedHashMap); // {Alice=30, Bob=25, Charlie=30, David=25}
    	
    }
}

 

2. 특정 타입의 컬렉션으로 변환 - toCollection()

public class CollectExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "Apple");

        // ArrayList로 변환
        ArrayList<String> arrayList = fruits.stream()
                .collect(Collectors.toCollection(ArrayList::new));
        System.out.println("arrayList: " + arrayList);  // arrayList: [Apple, Banana, Cherry, Apple]

        // treeSet으로 변환
        TreeSet<String> treeSet = fruits.stream()
                .collect(Collectors.toCollection(TreeSet::new));
        System.out.println("treeSet: " + treeSet);  // treeSet: [Apple, Banana, Cherry]

    }
}

 

3.문자열 결합 - joining()

스트림 요소를 하나의 문자열로 합칩니다.

public class CollectExample {
    public static void main(String[] args) {
    	List<String> words = Arrays.asList("Java", "Stream", "API");

    	String result = words.stream()
    	        .collect(Collectors.joining(", "));

    	System.out.println(result); // Java, Stream, API
    }
}

 

4. 값 합산, 평균, 통계 - summingInt(), averagingInt(), summarizingInt()

public class CollectExample {
    public static void main(String[] args) {
    	List<Integer> numbers = Arrays.asList(3, 5, 8, 10);

    	int sum = numbers.stream()
    	        .collect(Collectors.summingInt(Integer::intValue));

    	double avg = numbers.stream()
    	        .collect(Collectors.averagingInt(Integer::intValue));

    	IntSummaryStatistics stats = numbers.stream()
    	        .collect(Collectors.summarizingInt(Integer::intValue));

    	// Sum: 26
    	System.out.println("Sum: " + sum); 
    	// Avg: 6.5
    	System.out.println("Avg: " + avg); 
    	// Stats: IntSummaryStatistics{count=4, sum=26, min=3, average=6.500000, max=10}
    	System.out.println("Stats: " + stats);
    }
}

 

5. 그룹화 - groupingBy()

public class CollectExample {
    public static void main(String[] args) {
    	List<String> names = Arrays.asList("Alice", "Ava", "Bob", "Charlie", "Chan", "David", "Eva");

        // 첫 글자를 기준으로 이름 그룹화
        Map<Character, List<String>> groupedByFirstLetter = names.stream()
            .collect(Collectors.groupingBy(name -> name.charAt(0))); // 첫 글자를 기준으로 그룹화

        System.out.println(groupedByFirstLetter);
        // {A=[Alice, Ava], B=[Bob], C=[Charlie, Chan], D=[David], E=[Eva]}
    }
}
class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name;
    }
}

public class CollectExample {
    public static void main(String[] args) {
    	List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 30),
                new Person("David", 25)
        );

        // 나이별 그룹화
        Map<Integer, List<Person>> groupedByAge = people.stream()
                .collect(Collectors.groupingBy(person -> person.age));
        
        // {25=[Bob, David], 30=[Alice, Charlie]}
        System.out.println(groupedByAge);
    }
}

 

6. 그룹화 + 개수 세기 - groupingBy() + counting()

class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name;
    }
}

public class CollectExample {
    public static void main(String[] args) {
    	List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 30),
                new Person("David", 25)
        );

    	Map<Integer, Long> countByAge = people.stream()
    	        .collect(Collectors.groupingBy(person -> person.age, Collectors.counting()));

    	System.out.println(countByAge); // {30=2, 25=2}
    }
}

 

7. 조건에 따른 분할  - partitioningBy()

class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name;
    }
}

public class CollectExample {
    public static void main(String[] args) {
    	List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 30),
                new Person("David", 25)
        );

    	Map<Boolean, List<Person>> partitioned = people.stream()
    	        .collect(Collectors.partitioningBy(person -> person.age >= 30));

    	System.out.println(partitioned);
    }
}

정리

collect()는 Java Stream API에서 매우 중요한 메서드로, 다양한 방식으로 데이터를 집계하는 데 사용됩니다. Collectors.toList(), Collectors.toSet(), Collectors.toMap() 외에도 그룹화, 합산, 평균 계산, 요소 결합 등 여러 가지 유용한 방법들이 제공되므로 필요에 따라 적절히 활용할 수 있습니다.

1. Java Stream API 이란?

Java Stream API는 Java 8에서 도입된 기능으로, 컬렉션(List, Set, Map 등)의 데이터를 함수형 스타일로 처리할 수 있도록 지원하는 기능입니다. Stream은 데이터 소스(컬렉션, 배열 등)를 처리하는 데 사용됩니다.


2. Stream API의 주요 특징

  • 데이터 처리 중심: 컬렉션 요소를 반복하지 않고 함수형 프로그래밍 방식으로 데이터를 처리
  • 연산 체이닝(Chaining): 여러 연산을 조합하여 선언적으로 처리 가능
  • 내부 반복(Internal Iteration): 루프 없이 병렬 처리 최적화
  • Immutable(불변성): 원본 데이터를 변경하지 않고 새로운 데이터를 생성

3. Stream 생성

스트림은 컬렉션, 배열, 또는 직접 값을 통해 생성할 수 있습니다.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamExample {
    public static void main(String[] args) {
        // 컬렉션에서 스트림 생성
        List<String> list = Arrays.asList("apple", "banana", "cherry");
        Stream<String> stream1 = list.stream();
        stream1.forEach(System.out::println);

        // 배열에서 스트림 생성
        String[] array = {"dog", "cat", "bird"};
        Stream<String> stream2 = Arrays.stream(array);
        stream2.forEach(System.out::println);

        // 직접 값으로 스트림 생성
        Stream<String> stream3 = Stream.of("one", "two", "three");
        stream3.forEach(System.out::println);
        
        // 무한 스트림 생성
        Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
        infiniteStream.forEach(System.out::println);
    }
}

4. Stream API 사용법(주요기능)

데이터의 필터링, 매핑, 정렬, 집계 등 다양한 작업을 간결하고 가독성 좋게 작성할 수 있습니다.

 

필터링(filter)

특정 조건을 만족하는 요소만 추출합니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");

        // 길이가 5 이상인 과일만 필터링
        fruits.stream()
              .filter(fruit -> fruit.length() > 5)
              .forEach(System.out::println); // 출력: banana, cherry
              
        // "apple"만 남김      
        fruits.stream()
              .filter(s -> s.startsWith("a"))  
              .forEach(System.out::println); // 출력: apple
    }
}

 

매핑(map)

요소를 다른 형태로 반환합니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("apple", "banana", "cherry");

        // 모든 과일 이름을 대문자로 변환
        fruits.stream()
              .map(String::toUpperCase)
              .forEach(System.out::println); // 출력: APPLE, BANANA, CHERRY
        
        // 모든 요소를 2배 증가
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        numbers.stream()
               .map(n -> n * 2)  
               .forEach(System.out::println);
    }
}

 

정렬(sorted)

요소를 정렬합니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("banana", "apple", "cherry");

        // 오름차순 정렬(알파벳 순으로 정렬)
        fruits.stream()
              .sorted()
              .forEach(System.out::println); // 출력: apple, banana, cherry
              
        // 내림차순 정렬
        fruits.stream()
             .sorted((a, b) -> b.compareTo(a))
             .forEach(System.out::println); // 출력: cherry, banana, apple
        
        // 오름차순 정렬
        List<Integer> numbers = Arrays.asList(1,2,3);
        numbers.stream()
              .sorted((a, b) -> a - b)  // 또는 sorted((a, b) -> a.compareTo(b))
              .forEach(System.out::println); // 출력: 1,2,3
        
        // 내림차순 정렬
        numbers.stream()
              .sorted((a, b) -> b - a)  // 또는 sorted((a, b) -> b.compareTo(a))
              .forEach(System.out::println); // 출력: 3,2,1
    }
}

 

특정 요소 선택 / 제외(limit(n) / skip(n))

특정 요소 선택 또는 제외 합니다.

import java.util.stream.Stream;

public class StreamExample {
	public static void main(String[] args) {
		Stream.of(1, 2, 3, 4, 5, 6)
	    	  .limit(3)  // 처음 3개 요소만 선택
	    	  .forEach(System.out::println);  // 출력: 1,2,3
		
		Stream.of(1, 2, 3, 4, 5, 6)
	    	  .skip(3)  // 처음 3개 요소 제외
	    	  .forEach(System.out::println);  // 출력: 4,5,6
    }
}

 

 

중복제거(distinct)

중복된 요소를 제거합니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("apple", "banana", "apple", "cherry");

        // 문자열 중복 제거
        fruits.stream()
              .distinct()
              .forEach(System.out::println); // 출력: apple, banana, cherry
              
        List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4);
        
        // 정수 중복 제거
        numbers.stream()
               .distinct()
               .forEach(System.out::println);  // 출력: 1,2,3,4
    }
}

 

집계 (count, sum, min, max, average)

요소의 개수, 합계, 최소값, 최대값, 평균 등을 계산합니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 합계 계산
        int sum = numbers.stream()
                         .mapToInt(Integer::intValue)
                         .sum();
        System.out.println("Sum: " + sum); // 출력: Sum: 15

        // 평균 계산
        double average = numbers.stream()
                                .mapToInt(Integer::intValue)
                                .average()
                                .orElse(0);
        System.out.println("Average: " + average); // 출력: Average: 3.0
    }
}

 

리듀스(reduce)

요소를 결합하여 단일 결과를 생성합니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 모든 숫자의 곱 계산
        int product = numbers.stream()
                             .reduce(1, (a, b) -> a * b);
        System.out.println("Product: " + product); // 출력: Product: 120
        
        // 모든 숫자의 합 계산
        int sum = Stream.of(1, 2, 3, 4, 5).reduce(0, (a, b) -> a + b);
		System.out.println(sum);  // 15
    }
}

 

조건검사(anyMatch, allMatch, noneMatch)

요소가 특정 조건을 만족하는지 검사합니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 모든 요소가 0보다 큰지 확인
        boolean allPositive = numbers.stream()
                                     .allMatch(n -> n > 0);
        System.out.println("All positive: " + allPositive); // 출력: All positive: true

        // 3보다 큰 요소가 하나라도 있는지 확인
        boolean anyGreaterThanThree = numbers.stream()
                                             .anyMatch(n -> n > 3);
                                             
        // 출력: Any greater than 3: true
        System.out.println("Any greater than 3: " + anyGreaterThanThree); 
    }
}

 

그룹화(groupingBy)

요소를 특정 기준으로 그룹화합니다.

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

public class StreamExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");

        // 과일 이름의 길이로 그룹화
        Map<Integer, List<String>> groupedByLength = fruits.stream()
                .collect(Collectors.groupingBy(String::length));

        System.out.println(groupedByLength);
        // 출력: {5=[apple], 6=[banana, cherry], 4=[date]}
    }
}

 

병렬 스트림(parallelStream)

병렬 처리를 통해 성능을 향상시킵니다.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");

        // 병렬 스트림으로 처리
        fruits.parallelStream()
              .forEach(System.out::println); // 순서가 보장되지 않음
    }
}

 


5. Stream 활용 예제

짝수만 필터링 후 제곱 값 리스트 생성
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamExample {
	public static void main(String[] args) {
		List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
		List<Integer> result = numbers.stream()
		    .filter(n -> n % 2 == 0)
		    .map(n -> n * n)
		    .collect(Collectors.toList());

		System.out.println(result);  // [4, 16, 36]

    }
}

 

문자열 리스트에서 가장 긴 단어 찾기
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class StreamExample {
	public static void main(String[] args) {
		List<String> words = Arrays.asList("apple", "banana", "cherry", "watermelon");
		String longestWord = words.stream()
		    .max(Comparator.comparingInt(String::length))
		    .orElse("No words");

		System.out.println(longestWord);  // watermelon
    }
}

 

특정 키워드를 포함하는 개수 구하기
import java.util.stream.Stream;

public class StreamExample {
	public static void main(String[] args) {
		long count = Stream.of("java", "javascript", "python", "c++")
			    .filter(s -> s.contains("java"))
			    .count();

			System.out.println(count);  // 2

    }
}

 

forEach, count, collect 사용
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamExample {
	public static void main(String[] args) {
		Stream.of("A", "B", "C").forEach(System.out::println); // 출력: A, B, C
		
		long count = Stream.of(1, 2, 3, 4, 5).count();
		System.out.println(count);  // 출력: 5

		// 스트림에서 List 저장
		List<String> list = Stream.of("A", "B", "C").collect(Collectors.toList()); 
		System.out.println(list);
    }
}

6. 정리

Java의 Stream API는 컬렉션 데이터를 처리하는 데 매우 강력한 도구입니다. 위의 예제들은 Stream의 주요 기능을 보여주며, 이를 활용하면 데이터를 효과적으로 처리하면서 코드를 더 간결하고 가독성 있게 작성할 수 있습니다. 상황에 맞게 적절한 기능을 선택하여 사용하면 됩니다. 또한 병렬 스트림을 활용하면 성능 최적화도 가능합니다.

'BackEnd > JAVA' 카테고리의 다른 글

[JAVA] 정규식 사용 정리  (0) 2025.02.20
[JAVA] Stream API Collect 메소드  (0) 2025.02.20
[JAVA] Checked Exception과 Unchecked Exception 차이점  (0) 2025.02.13

 

자바에서 예외(Exception)는 크게 Checked Exception과 Unchecked Exception으로 나뉩니다.

1. Checked Exception

개념

- 컴파일 시점에 반드시 예외 처리를 해야 하는 예외
- try-catch 문으로 처리하거나 throws 키워드를 사용하여 호출자에게 예외 처리를 위임해야 함
- 예외 처리를 하지 않으면 컴파일 오류 발생

 

대표적인 Checked Exception

- IOException → 파일 입출력 시 발생
- SQLException → 데이터베이스 관련 예외
- ClassNotFoundException → 클래스 로드 실패
- InterruptedException → 스레드 인터럽트 발생

 

예제

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class CheckedExceptionExample {
    public static void main(String[] args) {
        try {
            File file = new File("test.txt");
            FileReader fr = new FileReader(file); // FileNotFoundException 발생 가능
        } catch (IOException e) { // IOException을 반드시 처리해야 함
            System.out.println("파일을 찾을 수 없습니다: " + e.getMessage());
        }
    }
}

 


2. Unchecked Exception

개념

- 런타임(Runtime)에서 발생하는 예외
- 컴파일 시점에서는 예외 처리를 강제하지 않음
- 대부분 프로그래머의 실수로 인해 발생

 

대표적인 Unchecked Exception

- NullPointerException → null 객체에 접근
- ArrayIndexOutOfBoundsException → 배열의 인덱스를 초과
- ArithmeticException → 0으로 나누기
- ClassCastException → 잘못된 형 변환

 

예제

public class UncheckedExceptionExample {
    public static void main(String[] args) {
        String text = null;
        System.out.println(text.length()); // NullPointerException 발생
    }
}

 


3. Checked vs Unchecked 차이점 비교

 

구분 Checked Exception Unchecked Exception
예외 처리 여부 반드시 처리해야 함 (try-catch 또는 throws) 강제되지 않음 (개발자가 직접 처리 가능)
컴파일 단계 예외 처리를 하지 않으면 컴파일 오류 발생 컴파일 단계에서 예외 검사 없음
발생 시점 파일 I/O, 네트워크, DB 작업 등 외부 시스템과 연관된 예외 null, 배열 범위 초과, 0 나누기 등 코드 문제로 발생
예제 IOException, SQLException, ClassNotFoundException NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException

 


4. 언제 Checked vs Unchecked를 사용해야 할까?

1) Checked Exception을 사용할 때

- 외부 시스템(파일, DB, 네트워크 등)과 관련된 오류를 예상할 수 있는 경우
- 개발자가 반드시 예외 처리를 강제해야 하는 경우

 

2) Unchecked Exception을 사용할 때

- 프로그래머의 실수로 인해 발생할 가능성이 높은 경우
- NullPointerException, IndexOutOfBoundsException 등 논리적인 오류가 주된 원인인 경우

 


5. 요약

- Checked Exception → 개발자가 반드시 처리해야 하는 예외, 컴파일 할 때 예외에 대한 처리를 강제.
- Unchecked Exception → 프로그램 로직 오류로 발생하는 예외, 강제 예외 처리는 필요 없음, 예외에 대한 처리를 강제하지 않음.

 

Checked Exception은 외부 시스템과의 통신 오류, Unchecked Exception은 개발자가 잘못된 코드를 작성했을 때 발생한다고 기억하면 됩니다!

'BackEnd > JAVA' 카테고리의 다른 글

[JAVA] 정규식 사용 정리  (0) 2025.02.20
[JAVA] Stream API Collect 메소드  (0) 2025.02.20
[JAVA] Stream API 생성과 사용법 정리  (2) 2025.02.15

+ Recent posts