리액티브 스트림의 이해

web/마이크로서비스|2018. 10. 4. 23:47

리액티브 스트림은 총 4개의 인터페이스로 구성되어 있다. 

ㅁ 발행자(Publisher) 

- 데이터의 소스를 가지고 있으며 Subscriber의 요청이 오면 데이터를 발행한다. 구독자는 발행자에 대한 구독을 추가할 수 있다. Subscribe 메소드를 통해서 구독자를 추가할수 있다.

1
2
3
public interface Publisher<T> {
    public void subscribe(Subscriber<? Super T> s);
}
cs


ㅁ 구독자 (Subscriber) 

-  구독자는 데이터 스트림을 소비하기 위해 발행자를 구독한다. 구독자는 다양한 메서드를 제공하는데 대부분의 메서드가 콜백으로 등록되어 사용된다.

1
2
3
4
5
6
public interface Subscriber<T> {
  public void onSubscribe(Subscription s);
  public void onNext(T t);
  public void onError(Throwable t);
  public void onComplete();
}
cs


ㅁ 구독 (subscription) 

단 하나의 발행자와 단 하나의 구독자를 연결해주며 그 둘 사이에서만 데이터 교환을 중재한다. 데이터 교환은 구독자의 request 메서드 호출로 실행되고 cancel로 종료된다.

1
2
3
4
public interface Subscription {
  public void request(long n);
  public void cancel();  
cs


ㅁ 프로세서 (procesor) 

프로세서는 처리 단계를 나타내며, 발행자 인터페이스와 구독자 인터페이스를 모두 상속한다. 프로세서는 발행자와 구독자 사이의 계약을 반드시 준수해야한다. 프로세서는 발행자와 구독자를 연결해서 chaining(메서드가 반환하는 객체를 다른 변수에 할당하지 않고 객체가 가지고 있는 메소드를 호출하는 것)을 할 수도 있다.

1
2
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}
cs



리액터에는 발행자 플로세서로 사용되는 flux와 mono가 있다. flux는 0 또는 N개의 이벤트를 발행할 수 있고, Mono는 0 또는 1 개의 이벤트만 발행할 수 있다. 그래서 다수의 데이터 요소 또는 값의 리스트를 스트림으로 전송할 때만 사용된다.

댓글()

규칙 62 - 메서드에서 던져지는 모든 예외에 대해 문서를 남겨라.

JAVA/Effective Java|2018. 6. 1. 23:17

메서드를 올바르게 사용하려면 메서드에서 던져지는 예외에 대한 설명이 문서에 있어야 한다.


그리고 


메서드가 던질수있는 모든 무점검 예외까지 선언할 필요는 없지만 점검지점 예외들과 마찬가지로주의해서 문서로 남겨놓으면 좋다.


특히 Javadoc @throws 태그를 사용해서 메서드에서 발생 가능한 모든 무점검 예외에 대한 문서를 남겨야 한다. 하지만 메서드 선언부의 throws 뒤에 무점검 예외를 나열하지는 말아야 한다.





요약하자면 메서드가 던질 가능성이 있는 모든 예외를 문서로 남겨라. 

점검지점 예외, 무점검 예외도 남겨라.



이를 지키지 않으면 해당 API를 사용하는 다른사람들이 효과적으로 사용하는게 어려워진다.




출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙62 인용

댓글()

Java8 함수형 인터페이스 만들어서 사용하기

JAVA/Java 8|2018. 5. 31. 07:46

Java8 함수형 인터페이스 만들어서 사용하기

함수형 인터페이스 사용 
-> 정의한 함수형 인터페이스를 람다식을 이용하여 사용할 수 있다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//     함수형 인터페이스 선언 
//  함수형 인터페이스를 만들고자 할 경우에는 @FunctionalInterface 애노테이션을 붙혀야 한다.
 
@FunctionalInterface
public interface WedulInterface {
    public void print(int x);
}
 
public static void main(String args[]) {
    WedulInterface wedul = new WedulInterface() {
        @Override
        public void print(int x) {
            System.out.println(x);
        }
    };
        
    List<Integer> a = Arrays.asList(1,23);
    a.stream().forEach(wedul::print);
}
cs





댓글()

자바 8에서 java.util.function 패키지에 추가된 기본 함수형 인터페이스 정리

JAVA/Java 8|2018. 5. 31. 07:45

자바 8에서 java.util.function 패키지에 추가된 기본 함수형 인터페이스 정리

Function <T, R> 
=> T 입력으로 R 출력하여 반환



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Java8Test {
 
    public static void main(String args[]) {
        
        Function<String, Integer> mapStrToInt = new Function<String, Integer>() {
            public Integer apply(String str) {
                if (str == "wedul") {
                    return 1;
                }
                return 2;
            }
        };
        
        List<String> testData = Arrays.asList("wedul","dd","babo");
        testData.stream().map(mapStrToInt).forEach(System.out::println);
    }
}
cs




Predicate<T> 
-> T 입력으로 boolean 출력으로 반환


1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String args[]) {
        
    Predicate<Integer> predictData = new Predicate<Integer> () {
        @Override
        public boolean test(Integer tes) {
            return tes > 10
        }
    };
        
    List<Integer> test = Arrays.asList(12,3,4,55);
        
    test.stream().filter(predictData).forEach(System.out::println);
}
cs



Consumer <T>  
-> T 입력으로 아무것도 반환하지 않는다
-> 단순하게 입력받은 데이터를 처리할때 사용된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String args[]) {
        
    Consumer<Integer> consumerData  = new Consumer<Integer>() {
        @Override
        public void accept(Integer idnt) {
            System.out.println(idnt);
        }
    };
        
    List<Integer> test = Arrays.asList(12,3,4,55);
        
    test.stream().forEach(consumerData);
}
cs




Supplier<T> : 입력을 취하지 않고 T 반환
입력한 데이터를 가지고 있으며get 메소드를 사용하여 호출한 곳에서 입력된 데이터를 사용할  있게 반환  주는 기능 제공



1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String args[]) {
        
    Supplier<Integer> supplier = new Supplier<Integer>() {
        @Override 
        public Integer get() {
            return 1;
        }
    };
        
//        List<Integer> test = Arrays.asList(12,3,4,55);
    System.out.println(supplier.get());
}
cs


댓글()

Java8 인터페이스의 정적 메소드

JAVA/Java 8|2018. 5. 30. 07:42

인터페이스의 정적 메소드
 
 Java 8 부터는 인터페이스에 정적 메소드를 추가할  있다.
원래부터 인터페이스에 정적 메소드를 추가하면 안되는 이유는 없었으나단지 추상 명세로서 변하면 안된다는 인터페이스의 정신에 어긋 나는 것으로 여겨져 금지되어 왔다.




지금 까지는 일반적으로 인터페이스와 동반하는 클래스들에 정적 메소드를 두었다.

하지만 이제는 사용이 가능하다.





'JAVA > Java 8' 카테고리의 다른 글

Java8 스트림(stream) 연산  (0) 2018.05.31
Java8 스트림(Stream) API  (0) 2018.05.31
Java8 인터페이스의 정적 메소드  (0) 2018.05.30
Java8 인터페이스 default Method (디폴트 메소드)  (0) 2018.05.30
Java8 변수 유효 범위  (0) 2018.05.30
Java8 생성자 레퍼런스  (0) 2018.05.30

댓글()

Java8 기초 설명

JAVA/Java 8|2018. 5. 30. 07:29

Java8과 Java7은 많은 부분이 바뀌어서 이제

Java8을 모르는 사람은 다른사람들과 협업하기 어려워 질 수도 있다.
작년에 공부하였던 부분을 다시 복습 할겸 포스팅을 진행한다.

Java8이 도입되면서 많이 변경된 부분이 함수형 프로그램이 가능하도록 되었다는 것이다.
그것의 중심에는 람다식 표현식이 있다.

람다 표현식(lambda expression)
 람다식 이란? 
단순히 정의하면프로그래밍에서 식별값 없이 실행   있는 함수 표현 방법함수를 변수에 할당파라미터로 전달하는게 가능
이미 많은 언어에서 지원하고 있다. Ruby, C#, Python,,,,,
그러나 자바는 함수형 프로그램 언어가 아니 여서 기존에 사용할  없었다.
 
 함수형 인터페이스(functional interface)
 함수 인터페이스functional interface는 단 하나의 추상 메소드가 정의 가능한 인터페이스이다. 인터페이스가 함수형 인터페이스임을 나타내는 수단으로서 FunctionalInterface 어노테이션이 도입되었다. 예를 들어, java.lang.Runnable은 다음과 같은 함수 인터페이스를 지닌다.
    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
하지만, 어노테이션을 통해 명시적으로 지정하지 않더라도 함수 인터페이스의 정의를 만족하는 인터페이스라면 자바 컴파일러가 주석의 유무에 상관없이 함수 인터페이스로서 취급한다
 
 람다식 기본 구성
 
  (int x, int y) -> { return x + y; }
  (x, y) -> x + y
  x -> x * x
  () -> x
  x -> { System.out.println(x); }
 
화살표(->) 왼쪽은 매개변수 목록  입력 값 유형이고오른쪽은 몸체  동작에 대한 정의이다.




1
2
3
4
5
6
7
8
9
10
// 람다 표현식 기본 예제
public class Java8Test {
    public static void main(String args[]) {
        Thread testThread = new Thread(() -> { 
            System.out.println("best wedul");
        });
        
        testThread.start();
    }
}
cs





※ 이미지 참조 : slideshare



 매개변수 타입 추론



매개변수 타입 추론 1.
numbers.forEach((Integer value) -> System.out.println(value));

-- forEach 메소드와 Consumer 인터페이스 
numbers.forEach(new Consumer<Integer>() {
    public void accept(Integer value) {
        System.out.println(value);
    }
});

 위의 예제의 경우 자바 컴파일러가 람다식을 분석해 Consumer 인터페이스의  구현된 메소드(accept) 동일한 타입(시그니처)인지 검사하고람다식을 마치 Consumer 인터페이스를 구현한 클래스의 인스턴스인  처럼 사용한다.
 
 또한 람다 식의 인수의 타입 선언은  부분의 경우 컴파일러가 추론할  있고다음과 같이 생략이 가능하다.
numbers.forEach(value -> System.out.println(value)); 





매개변수 타입 추론 2.


1
2
3
4
5
6
7
8
9
b.addActionListener((ActionEvent e -> {
   Text.setText("버튼 클릭");
});
 
Public void addActionListener(ActionListener l) {
   Public interface ActionListener{
     Void actionPerforemd(ActionEvent e)
  }
}
cs



자바 컴파일러가 람다식을 분석해 ActionListener 인터페이스의  구현된 메소드(actionPerformed) 동일한 타입인지 검사한다.


 람다식 장점 
 
코드의 간결성 : 효율적인 람다 함수의 사용을 통하여 불필요한 코드를 삭제할  있다.
 - 필요한 정보만을 사용하는 방식을 통한 퍼포먼스 향상 : 지연 연산을 지원하는 방식을 통하여 효율적인 퍼포먼스를 기대


'JAVA > Java 8' 카테고리의 다른 글

Java8 인터페이스의 정적 메소드  (0) 2018.05.30
Java8 인터페이스 default Method (디폴트 메소드)  (0) 2018.05.30
Java8 변수 유효 범위  (0) 2018.05.30
Java8 생성자 레퍼런스  (0) 2018.05.30
Java8 메서드 레퍼런스  (0) 2018.05.30
Java8 기초 설명  (0) 2018.05.30

댓글()

클래스와 인터페이스 - 규칙22 멤버 클래스는 가능하면 static으로 선언하라.

JAVA/Effective Java|2018. 5. 29. 22:43

중첩 클래스 (nested class)는 다른 클래스안에 선언된 클래스이다. 

이런 중첩 클래스는 4가지 종류로 구성되어있다.
1. static member class
2. non-static member class
3. anonymous class
4. local class.

2 ~ 4번 클래스는 내부 클래스(inner class)이다.


상황별 중첩 클래스 사용

그럼 위에 출력한 4가지의 중첩 클래스의 적절한 사용 시기를 알아보자.

1. 정적 멤버 클래스 (static member class)
- 정적 멤버 클래스는 바깥 클래스의 모든 멤버에 접근할 수 있다. (private 멤버 변수도 접근 가능)
- 다른 정적 멤버와 동일하게 접근 권한 규칙을 따른다.
- private static member class로 선언할 시 해당 클래스에 접근 가능한 클래스는 바깥 클래스이다.

2. 비 정적 멤버 클래스 (nonstatic member class)
- 비 정적 클래스 객체는 바깥 클래스 객체와 바로 연동이된다.
=> 바깥 클래스의 메소드도 호출 할 수 있으며, this 키워드를 통해 바깥 객체에 대한 참조도 얻을 수 있다. (this  키워드를 사용하여 바깥 클래스를 접근 하기 위해서는 바깥 클래스 이름을 기재하여 사용해야 한다. ClassName.this )
- 정적 클래스와 달리 단독으로 존재 할 수 없다.


위와 같은 이유로
비정적 클래스를 사용할 경우에는 바깥 클래스의 멤버 요소들을 사용하지 않아도 
접근이 가능하기 때문에 시간과 공간 요구량이 늘어난다. ( 이는 garbage collection이 쓰레기 처리하는데 어렵게한다.)

그러므로
바깥 클래스의 내부요소에 접근하지 않을 경우에는 
무조건 정적 클래스로 선언해야 한다.


3. 익명 클래스 (anonymous class)
- 익명 클래스는 사용하는 순간에 선언하고 객체를 만든다.
- 표현식 문법을 준수



댓글()

클래스와 인터페이스 - 규칙 21 전략을 표현하고 싶을 때는 함수 객체를 사용하라.

JAVA/Effective Java|2018. 5. 29. 22:41

호출 대상에 대해 어떠한 작업을 수행하는 것을

전략 패턴이라고 한다.



1
2
3
4
5
class StringCompare {
 public int compare (String s1, String s2) {
   return s1.length() - s2.length();
 }
}
cs



 두 개의 문자열을 받아서 비교하는 클래스를 사용할 수 있는 전략 패턴이다.
비교가 필요할 경우 매번 StringCompare 클래스를 생성하지 말고, 싱글톤 패턴을 정의하여 가져다가 사용하면 더욱 편리하다.

하지만 이 StringCompare 클래스의 경우 객체를 메서드에 전달하기 위해서는 인자의 자료형이 String이어야 한다. 

따라서 Compareator 인터페이스를 정의 하여 이를 StringComapre 클래스가 구현하도록 해야 한다.



1
2
3
4
5
6
7
8
9
10
11
// 인터페이스
public interface Comparator<T> {
  public int compare(T t1, T t2);
}
 
class StringCompare implements Comparator<String> {
  @Override 
  public int compare (String s1, String s2) {
   return s1.length() - s2.length();
  }
}
cs




정리하면,
 함수 객체의 주된 용도는 전략 패턴이다. 전략 패턴을 사용하기 위해서는 인터페이스 (위에서는 Comparator<String>)를 선언하고, 실행가능 전략 클래스 생성 시 저 위에 인터페이스를 구현하도록 해야 한다.

단, 전략 패턴이 한번만 사용할 경우 익명 클래스로 사용할 수 있다.



1
2
3
4
5
6
Arrays.sort(StringArray, new Comparator<String>() {
  @Overide
  public int compare (String s1, String s2) {
    return s1.length() - s2.length();
  }
});
cs



만약 자주 사용 되는 경우에는,
public static final 지시자를 사용하여 외부에 공개 할 수 있다.



1
2
3
4
5
6
7
8
9
10
11
class Host {
  private static Class StringCompare implements Comparator<String>, Serializable {
   public int comapare(String s1, String s2) {
    return s1.length() - s2.length();
   }
  }
 
  // Compare<String>를 구현한 클래스로, 다형성을 이용하여 StringCompare를 받을 수 있다.
  // 외부에서는 Host.STRING_LENGTH_COMPARATOR.compare("dd", "ff"); 방식으로 사용할 수 있다.
  public static final Comparator<String> STRING_LENGTH_COMPARATOR = new StringCompare();
}
cs



출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙21 인용.



댓글()