본문 바로가기

자바☕

11. 16 JAVA 기초 강의: 제너릭스/ 람다/ 스트림API/ 네트워킹

728x90

1. 제너릭스 ~ Generic: 데이터의 타입을 일반화한다

다양한 타입의 객체들을 다루는 메소드나 컬렉션 클래스에 컴파일 시 타입 체크

동작은 같지만 타입이 달라지는 경우에 유용하게 사용할 수 있다.

->장점

1. 객체 타입을 컴파일 시 체크하기 때문에 안정성이 높아진다

2. 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있다.

클래스나 메소드에서 사용할 내부 테이터 타입을 컴파일 시 미리 지정하는 방법

 

*제너릭스를 사용하지 않으면 제너릭 클래스 안에 있는 객체를 꺼낼 때마다 형변환을 해줘야 한다.

*제너릭 타입이 조상클래스와 자손클래스로 다르게 입력되어서는 안된다.

ArrayList<TV> list = new ArrayList<TV>();

ArrayList<TV> list = new ArrayList<SmartTv>(); // 제너릭 에러

List<Tv> list = new ArrayList<Tv>(); // ArrayList가 List를 구현
//클래스 타입 간 다형성 적용, 제너릭 타입은 일치해야 한다.

 

Collection 클래스의 toArray 메서드 :

default <T> T[] toArray(IntFunction<T[]> generator) {
        return toArray(generator.apply(0));
    }

 

Collection 클래스의 ContainsAll 메서드 :

boolean containsAll(Collection<?> c);

 

Collection 클래스의 addAll 메서드 :

boolean addAll(Collection<? extends E> c);

 

2. 람다식

식별자 없이 실행가능한 함수(익명함수)

람다식이 비효율적일 수도 있는 이유

1. 람다를 사용해 만든 익명함수는 재사용이 불가능

2. 람다만을 사용할 경우 비슷한 메소드를 중복되게 생성할 가능성이 있어 코드의 비효율이 발생할 수 있다

3. 스트림: 데이터의 흐름

컬렉션을 통해 스트림을 활용: 각각의 데이터에 대해 어떻게 대응할 지를 정할 수 있다.

스트림은 작업을 내부 반복 처리 및 데이터소스를 변경하지 않는다.

컬렉션의 요소를 모두 읽고 나면 닫혀서 재사용이 불가능하다. 그러므로 필요할 경우 재생성을 해야한다.

스트림 프로세스

1. 스트림 생성

Stream<T> Collection.stream() 을 이용하여 해당하는 컬렉션을 기반으로하는 스트림을 생성

2. 중간 연산

중간 단계로써 데이터의 형변환 혹은 필터링, 정렬 등 스트림에 대한 가공 :

map(변환) / sorted(정렬) / skip(스트림 자르기) / limit(스트림 자르기) 등

3. 최종 연산

스트림의 요소를 소모해서 결과를 반환하는 단계, 최종 연산 이후 스트림이 닫히게 되고 더 이상 사용할 수 없다.

최종 연산의 결과값은 단일 값일 수도 있으며 배열 혹은 컬렉션일 수도 있다.

가장 많이 쓰이는 패턴:

collect()를 이용해서 다른 콜렉션으로 바꾸기, reduce를 이용해서 incremental calculation(증분 계산)

 

람다 & 스트림 예제

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

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("korea");
        list.add("japan");

        Stream<String> stream = list.stream();
        /*stream.map(str -> str.toUpperCase()). //대문자로 바꿔주는 함수
                forEach(it -> System.out.println(it));*/
        // 스트림: 데이터 소스를 변경하지 않는다!
        stream.map(str -> {
            System.out.println(str);
            return str.toUpperCase(); //대문자로 바꿔주는 함수, 중괄호 사용시
            // 함수처럼 return문을 사용해야 한다
        }).forEach(it -> System.out.println(it));

        System.out.println(list);
        stream.forEach(System.out::println); //스트림
    }
}

람다 & 스트림 예제 2)

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("서울");
        list.add("부산");
        list.add("대구");
        list.add("서울")
        System.out.println(list);

        List<String> result = list.stream() //리스트를 변경
                .limit(2) // limit을 이용해 개수
                .collect(Collectors.toList()); // 어떻게 모을지, 리스트로 만들거야(toList)

        System.out.println(result);
        System.out.println("list -> transformation -> set");
        /*Set<String> set = list.stream()
                .filter(it -> "서울".equals(it)) //서울만 남기는 필터
                .collect(Collectors.toSet());*/
        Set<String> set = list.stream()
                .filter("서울"::equals) //람다식으로 변환
                .collect(Collectors.toSet());

        System.out.println(set); // set은 중복을 허용하지 않는다
    }
}

예제 3)

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

public class Main {
    public static void main(String[] args) {
        String[] arr = {"SQL","Java", "Python"};
        Stream<String> stringStream = Arrays.stream(arr); // 스트림된 arr
        stringStream.forEach(System.out::println); //람다
    }
}

예제 4) Map 연산

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

import org.apache.commons.lang3.tuple.Pair;

class Sale {
    String fruitName;
    int price;
    float discount;

    public Sale(String fruitName, int price, float discount) {
        this.fruitName = fruitName;
        this.price = price;
        this.discount = discount;
    }
}

public class Main {
    public static void main(String[] args) {
        List<Sale> sales = Arrays.asList(
            new Sale("Apple", 5000, 0.05F),
            new Sale("Orange", 2000, 0.2F),
            new Sale("Grape", 3000,  0)
        );

        Stream<Sale> saleStream = sales.stream();
        saleStream.map(sale -> Pair.of(sale.fruitNmae, sale.price * (1-sale.discount)))
                .forEach(pair -> System.out.println(pair.getLeft() + " 실 구매가: " + pair.getRight() + "원"));
    }
}

예제 5)

public class Main {
    public static void main(String[] args) {
        List<Integer> numArr = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer result = numArr.stream().reduce(0, Integer::sum);
        //reduce와 sum을 활용하여 1부터 10까지 더하게 됩니다.
        System.out.println(result);
    }
}

4. 네트워킹

라이브러리 리트로핏

HTTP vs HTTPS : HTTPS는 보안된 HTTP 프로토콜

import retrofit2.Call;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        Call<Object> result = RetrofitClient.getApi().getUsers(2);

        try{
            System.out.println(result.execute().body());
        } catch (IOException e) {
            System.out.println(e. getMessage());
        }
    }
}
728x90