반응형

**스트림 api

=>java.io패키지에 있는 스트림은 입출력을 위한 스트림

=>java.util.stream패키지의 스트림은 Collection 에 대한 작업을 위한 스트림 -1.8버전에 추가

=>기존에는 동일한 자료형의 데이터 여러 개를 다룰 때 Collection이나 배열을 이용

Collection이나 배열을 이용하게 되면 코드가 길어지고 재사용성이 떨어집니다.

Collection과 배열에 있는 동일한 작업을 수행하는 메소드가 이름은 같은데 사용방법이 조금씩 다릅니다.

예를 들면 LIst의 정렬을 위한 sort메소드는 instance메소드인데 배열의 정렬을 위한 메소드는 Arrays클래스의 SORT라는 STATIC메소드입니다.

배열의 데이터를 하나씩 가져올 때는 [인덱스]를 이용하고 list의 데이터는 get(인덱스)을 이용합니다.

=>메소드의 매개변수로 인터페이스를 이용하는 경우에 별도의 클래스를 만들거나 anonymous class를 이용해야 해서 코드가 길어지고 메모리 낭비가 발생했는데 스트림api에서는 매개변수에 람다식을 사용해서 코드를 간결하게 만들 수 있습니다.

=>병렬처리도 쉽게 할 수 있음

 

1.배열의 데이터 접근

CollectionUse.java

public static void main(String[] args) {

                       //List의 데이터를 사용

                      

                       //배열을 이용해서 lIST만들기

                       List<String> list = Arrays.asList("C","Python","Java");

                      

                       //인덱스를 이용해서 하나씩 접근 - 배열이나 List의 데이터 개수를 알아야 합니다.

                       System.out.println();

                       System.out.println("데이터를 인덱스를 이용해서 하나씩 접근");

                       int length = list.size();

                       int i = 0;

                       //for보다 while이 좋다.

                       //for은 집단으로 접근하는게 좋다.

                       while(i < length) {

                                  String temp = list.get(i);

                                  System.out.println(temp);

                                  i++;

                       }

                      

                       System.out.println();

                       System.out.println("반복자(Iterator - Enumeration : __iter__:python)을 이용해서 하나씩 접근");

                       //반복자는 데이터 개수를 알 필요가 없습니다.

                       Iterator<String> iterator = list.iterator();

                       //다음 데이터 존재 여부를 확인하고 다음 데이터에 접근 - 데이터베이스에서는 Cursor라고 합니다.

                       //데이터베이스나 c++에서는 이런 방법으로 접근을 하지만 JavaPython같은 언어는 다른 방법을 제공

                       //간경해졌고 길이를 알 필요없다.

                       while(iterator.hasNext()) {

                                  System.out.println(iterator.next());

                       }

                      

                       System.out.println();

                       System.out.println("빠른 열거 (for-each)를 이용하는 방법");

                       //반복자가 구현된 객체의 경우는 빠른 열거를 사용하는 것이 가능

                       //예약어만 다른것이지 접근 방법은 똑 같다.

                       for(String temp: list) {

                                  System.out.println(temp);

                       }

                      

                      

                       System.out.println();

                       System.out.println("스트림을 이용하는 방법");

                       //스트림 생성

                       Stream<String> stream = list.stream();

                       //람다식을 이용해서 메소드의 내용을 매개변수로 대입 - 함수형 프로그래밍

                       //스트림을 만들때 사용한 Collection의 데이터를  name에 순서대로 대입해서 {}안의 내용을 수행

                       //반복문을 사용하지 않아도 forEach가 알아서 순서대로 실행

                       //python에서의 numpyndarray pandas Series, DataFrame등의 동작방식에 이와 동일

                       stream.forEach((name) -> {System.out.println(name);});

           }

 

2. 스트림의 특징

1)스트림은 데이터 소스를 변경하지 않습니다.

원본 데이터에 변경을 가하지 않습니다.

중간 연산한 결과를 별도로 저장할 수 있습니다.

 

2)스트림은 일회용

=>한 번 읽고 나면 재사용이 안되므로 다시 만들어서 사용

 

3)스트림은 작업을 내부적으로 반복해서 처리

=>반복문이 내부에 숨어있는 것 입니다.

=>단순하게 스트림을 사용한다고 해서 실행 속도가 빨라지는 것은 아닙니다.

 

4)다양한 기본 연산 제공

=>중간 처리 (매핑 - 변환, 필터링, 정렬) 연산과 최종 처리(반복 ,카운팅, 평균,합계)연산을 제공

 

5)스트림의 연산은 지연된 연산

=>중간 연산이 중간에 수행되는 것이 아니고 최종 연산을 수행하기 전에 수행

 

6)Fork & join을 이용해서 병렬처리를 구현하는 것보다 휠씬 쉽게 병렬 처리를 구현

 

 

3.Stream생성

1)Collection(List, Set)을 가지고 생성

 

 

2)배열을 가지고 생성

Arrays.stream(배열)

 

3)디렉토리 경로를 가지고 생성

Stream<Path> Files.list(Path path): path에 있는 모든 디렉토리 및 파일에 접근할 수 있는 스트림

 

4) 텍스트 파일의 내용을 줄 단위로 접근

Stream<String> BufferedReader.lines()

 

5)랜덤한 스트림

Random.doubles(), ints(), longs()를 이용

 

6)배열을 이용해서 스트림을 생성하고 모든 데이터 출력

 

똑같은 것을 여러개 할 수있다. 요즘에는 메모리를 많이 사용하지만 속도가 빠르다.

CollectionUse.java

//현재 디렉토리에 있는 pl.csv파일의 내용을 읽어서 문자열 배열 만들기

                       try {

                                  //파일을 읽을 수 있는 스트림을 생성

                                  BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\project\\JAVA_PROJECT\\java\\src\\java\\pl.csv")));

                                  //데이터 한 줄 읽기

                                  String line = br.readLine();

                                  //, 단위로 분할해서 문자열 배열로 만들기

                                  String [] ar  = line.split(",");

                                  Stream<String> stream1 = Arrays.stream(ar);

                                  //출력

                                  stream1.forEach(System.out::println);//System.out::println메소드 이름 을 할 수 있는 것

                                  br.close();

                       } catch (Exception e) {

                                  System.out.println("파일 내용 읽기 실패: "+e.getMessage());

                       }

 

텍스트 파일 데이터 읽어올때 발생하는 문제

 

123

처음에 1을 읽는다.

su : 0 su * 10 +('1' - '0')  => 1

su  su * 10 + ('2'-'0') =>12

계산기를 이렇게 바꾼다. 그래서 숫자를 문자로 해서 한다. 숫자 입력이 안되면 계산이 안된다.

0-> 48이다.

//현재 디렉토리에 있는 pl.csv파일의 내용을 읽어서 문자열 배열 만들기

               try {

                      //파일을 읽을 있는 스트림을 생성

                      BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\project\\JAVA_PROJECT\\java\\src\\java\\pl.csv")));

                      //데이터 읽기

                      String line = br.readLine();

                      //, 단위로 분할해서 문자열 배열로 만들기

                      String [] ar  = line.split(",");

                      Stream<String> stream1 = Arrays.stream(ar);

                      //출력

               stream1.forEach(System.out::println);//System.out::println메소드 이름 있는

                      br.close();

                     

                      //ar[3]에는 12345건이라는 문자열에 존재 - 12345라는 정수로 변환

                      int su  =0;

                      for(i = 0; i < ar[3].length(); i++) {

                             //한글 자씩 가져오기

                             char ch = ar[3].charAt(i);

                             // 숫자인지 확인

                             if(ch >= '0' && ch <= '9') {

                                    su = su * 10 +(ch - '0');

                             }else {

                                    break;//, 콤마 있을 빼기

                             }

                      }

                      System.out.println(su);

               } catch (Exception e) {

                      System.out.println("파일 내용 읽기 실패: "+e.getMessage());

               }

4.스트림의 중간 연산(Reduction)

map reduce비슷한 것이다.

=>데이터를  변환, 필터링, 정렬, 그룹화 하는 것 등이 있습니다.

1)distinct():중복 제거 - 요소의 equals 메소드를 가지고 비교해서 equals   true를 리턴할 경우를 중복으로 간주

2)Filter(): 조건에 맞는 데이터만 필터링

=>하나의 매개변수를 받아서 boolean을 리턴하는 메소드를 대입

=>스트림의 모든 데이터를 매개변수에 대입해서 true리턴한 데이터만 골라서 Stream으로 리턴

 

3)map(); 데이터를 변환

=>하나의 매개변수를 받아서 리턴을 해주는 메소드를 대입

하나받아서 바꿔야 하나깐 리턴해야 한다.

 

4)sorted():데이터를 정렬

=>매개변수가 없으면 Comparable 인터페이스의 compareTo메소드를 이용해서 비교한 후 오름차순 정렬행

=>매개변수로 Comparator인터페이스를 구현한 객체나 2개의 매개변수를 받아서 정수를 리턴하는 람다식을 대입하면 대입된 객체나 람다식에 의해서 오름차순 정렬

앞의 데이터가 크다라고 할때는 양수를 리턴하면 되고 같으면 0 뒤의 데이터가 클 때는 음수를 리턴

 

5)peek(): 모든 데이터를 순회하면서 작업을 수행

=>매개변수로 1개의 데이터를 설정하고 return 이 없는 메소드를 대입

 

5.중간 연산 실습

1) 변호, 이름 , 성별 ,나이 ,점수를 소유한 dto(Data Transfer Object -VO)크래스르 생성

Student.java

private int num;

       private String name;

       private String gender;

       private int age;

       private int score;

      

       //데이터가 없는 경웨 사용할 생성자

       public Student() {

               super();

       }

      

       //데이터가 제공되는 경웨 사용할 생성자 - 테스트 데이터를 빠르게 입력해서 확인하기 위해서 생성

       public Student(int num, String name, String gender, int age, int score) {

               super();

               this.num = num;

               this.name = name;

               this.gender = gender;

               this.age = age;

               this.score = score;

       }

      

       //접근자 메소드

       public int getNum() {

               return num;

       }

       public void setNum(int num) {

               this.num = num;

       }

       public String getName() {

               return name;

       }

       public void setName(String name) {

               this.name = name;

       }

       public String getGender() {

               return gender;

       }

       public void setGender(String gender) {

               this.gender = gender;

       }

       public int getAge() {

               return age;

       }

       public void setAge(int age) {

               this.age = age;

       }

       public int getScore() {

               return score;

       }

       public void setScore(int score) {

               this.score = score;

       }

      

       //데이터를 빠르게 확인하기 위한 메소드

       @Override

       public String toString() {

               return "Student [num=" + num + ", name=" + name + ", gender=" + gender + ", age=" + age + ", score=" + score

                             + "]";

       }

 

2)main메소드를 소유한 main메소드 생성

stream사용하고있을경우오류가난다 .

ReductionMain.java

c++은 예약어가 거의 없다.

public static void main(String[] args) {

               // 샘플 데이터 작성

               Student student1 = new Student(1,"강좌진","",28, 98);

               Student student2 = new Student(2,"유관순","",19, 89);

               Student student3 = new Student(3,"김구","",38, 99);

               Student student4 = new Student(4,"안중근","",29, 100);

               Student student5 = new Student(5,"남자현","",25,97);

              

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

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

              

               //distinct- 중복을 제거해주는 메소드

               String[] ar = {"데니스 리치히","귀도 로섬","제임스 고스링","데니스 리치히"};

               Stream<String> arStream =Arrays.stream(ar);

              arStream.distinct().forEach(System.out::println);

              

               //filter 원하는 데이터만 골라내는 것이다.

               //fileter - 조건에 맞는 데이터만 추출하는 중간 연산

               //fileter에는 매개변수 1개를 갖고 boolean 리턴하는 람다식을 대입

               Stream<Student> stream = list.stream();

               //score 90보다 데이터만 추출해서 출력

               //stream.filter((student)->{return student.getScore()>= 90;}).forEach(System.out::println);

               //gender 여인 데이터만 추출해서 출력

               stream.filter((student)->{return student.getGender().equals("");}).forEach(System.out::println);

               //filter 한번에 한번 밖에 안된다.

               //boolean 리턴한면 된다.

              

              

               //변환을 하는 것이고

               //return 해줘야 한다.

               //map() 데이터를 변환할 사용하는 메소드

               // 숫자 -> 문자열 , 문자열 -> 숫자 , 날짜 -> 문자열 , 인스턴스 -> 기본형

               //Student score 변환

               System.out.println();

               stream = list.stream();//스트림은 사용하면 소멸되기 때문에 다시 사용할 떄는 새로 생성해야 합니다.

               //어떤 메소드를 수행만 하는 경우에는 클래스이름 :: 메소드이름만 입력해도 됩니다.

               //stream.mapToInt((student)->{return student.getScore();}).forEach(System.out::println);

               //함수형 프로그래밍

       stream.mapToInt(Student::getScore).forEach(System.out::println);

               //합계 구하기 편하다. 점수만 출력 된다.

              

               System.out.println();

               //정렬 sorted

               //데이터 정렬은 sorted메소들 이용

               // 요소가 크기 비교가 가능하다면 바로 오름차순 정렬을 수행

               //요소가 크기비교가 불가능하다면 크기 비교가 가능한 메소드를 대입해야 합니다.

               //크기비교가 가능한 데이터는 속성을 하나만 가진 데이터들입니다.

               //기본 자료형, 문자열 ,날짜 정도가 하나의 데이터만을 가진 자료형입니다.

               //항상 예외가 되는 언어가 있다. c언어이다.

               //c언어는 stack .linkedList 만들어서 해야 한다. doubleLinekedList 3000라인 작성하면 된다.

               arStream = Arrays.stream(ar);

               //string 크기 비교가 가능하기 때문에 바로 오름차순 정렬

               arStream.sorted().forEach(System.out::println);

         //arStream.distinct().sorted().forEach(System.out::println);

              

               System.out.println();

               stream = list.stream();

               //student 여러개의 항목을 소유하고 있기 때문에 어떤 항목으로 크기 비료를 알지 못하기 때문에 예외가 발생

               //stream.sorted().forEach(System.out::println);

              

               //크기 비교하는 메소드를 만들어서 정렬

               //크기 비교를 때는 2개의 매개변수를 가지고 정수를 리턴하는 메소드를 만들면 됩니다.

               //양수를 리턴하면 앞에것이 크다고 간주하고 0이면 같다고 음수이며 뒤의 데이터가 크다고 간주

               // 123 < 65 잘못 될수 있다.

               //점수의 오름차순

              

               //숫자 데이터를 이용해서 비교하는 경우 - 오름차순

               //stream.sorted((a,b)->{return a.getScore()- b.getScore();}).forEach(System.out::println);

              

               //문자열인 경우는 compareTo 이용 - 순서를 변경하면 내림차순

               stream.sorted((a,b)->{return b.getName().compareTo(a.getName());}).forEach(System.out::println);

       }

 

3)중간 연산 메소드는 여러 연속해서 사용 가능

 

 

6. 최종 연산 메소드

=>마지막에 한번만 사용가능한 메소드

(여러번 사용할 수 가 없다.한번만 사용하는 것이다.)

 

1)매칭관 관련된 메소드

=>모두 boolean을 리턴

allMatch()

anyMatch()

noneMatch()

=>3가지 메소드 모두 filter와 동일한 메소드를 매개변수로 받아서 전부 true또는 하나 이상 true또는 모두 false로 리턴하는지 알려지는 메소드

 

2)데이터 개수

long count()

 

3)데이터 합계

int, long ,double sum()

 

4)평균

OptionalDouble average()

=>Optionalnulll을 저장할 수 있는 자료형을 최근에는 optional이라고 합니다.

평균은 null이 있을수 있다.그래서 데이터 확인하고 해야 한다.

 

5)최대값 및 최소값

OptionalXXX max()

OptionalXXX min()

 

6)누적 연산

OptionalXXX reduce()

현재 파이썬에서 동작하면 오류 난다. 버전 확인해야 한다.

 

7)모든 요소에게 메소드 수행

forEach()

 

8) 결과를 저장

R collect()

 

자바도 ,딥러닝 가능하는데 만들어진 것이 적어서 python등으로 한다.

 

7.Optional

=>어떤 클래스의 객체를 감싸는 클래스

=>null이 리턴될 가능성이 있을 때 이 데이터를 바로 사용하면 예외가 발생할 가능성이 존재하기 때문에 null여부를 확인하고 사용해야 합니다.

자바는 Optional이라는 자료형을 이용해서 null인 경우 다른 데이터로 치환할 수 있는 메소드를 제공합니다.

 

T get(): 값을 가져오고 null이면 예외 발생

T orElse(T 기본값 ): 결과가 null이면 기본값을 리턴

boolean isPresent(): null이면 false그렇지 않으면 true리턴

 

 

=>변형으로는 OptionInt, OptionalLong, OptionalDouble

LastMain.java

public static void main(String[] args) {

               //문자열 배열을 이용해서 스트림을 생성

               String [] ar = {"Python","Java","Closure","Scala","Kotlin","Swift","C#","C&C++","JavaScript"};

               Stream<String> asStream = Arrays.stream(ar);

              

               //match - 판별하는

               //배열의 모든 데이터가 3글자 이상인지 확인  - C# 때문에 false

               //anyMatch ture -any 하나라도 만족하면 true

               //noneMathc false -하나도 만족하는게 없으면 true

               boolean r = asStream.allMatch((language)->{return language.length() >3;});

               System.out.println(r);

               System.out.println();

              

               //집계 함수를 사용

               //글자가 5 이상이인 데이터의 개수를 파악

               // 샘플 데이터 작성

               Student student1 = new Student(1,"강좌진","",28, 98);

               Student student2 = new Student(2,"유관순","",19, 89);

               Student student3 = new Student(3,"김구","",38, 99);

               Student student4 = new Student(4,"안중근","",29, 100);

               Student student5 = new Student(5,"남자현","",25,97);

              

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

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

              

               Stream<Student> stream =list.stream();

               //점수의 합계 구하기

               int tot = stream.mapToInt(Student::getScore).sum();

               System.out.println("score 합계:" +tot);

               System.out.println();

              

               //남자 나이 합계

               stream =list.stream();

               tot = stream.filter((student)->{return student.getGender().equals("");}).mapToInt(Student::getAge).sum();

               System.out.println("남자 나이 합계: " +tot);

               System.out.println();

              

               stream =list.stream();

               long cnt = stream.filter((student)->{return student.getGender().equals("");}).mapToInt(Student::getAge).count();

               System.out.println("데이터 개수: " +cnt);

               System.out.println();

              

               //gender 데이터의 score 평균

               //optional 기존 자료형의 데이터를 warping 자료형

               stream =list.stream();

               OptionalDouble avg = stream.filter((student)->{return student.getGender().equals("");}).mapToInt(Student::getScore).average();

               //getAsDouble 가져오면 결과가 null 예외가 발생

               //orElse 에서 기본값을 설정하면 결과가 null 기본값을 리턴

               System.out.println("여자 score평균" +avg.orElse(0));

               System.out.println();

              

               //max min comparator.comparing자료형(비교형 데이터의 메소드) 대입하면 Optional<제너릭>으로 결과를 리턴

               //Score 최대값

               stream =list.stream();

               Optional<Student> re =stream.filter((student)->{return student.getGender().equals("");}).max(Comparator.comparingInt(Student::getScore));

               System.out.println("score 최대값:" +re.get());

              

               stream =list.stream();

               Optional<Student> result =stream.filter((student)->{return student.getGender().equals("");}).min(Comparator.comparingInt(Student::getScore));

               System.out.println("남자의 최저 점수:" +result.get());

       }

9.collect

=>collect를 이용해서 중간 결과를 ListSet으로 리턴받고자 하면 이 때는 Collect에 매개변수로 Collectors.toList또는 toSet을 대입하면 됩니다.

 

 

=>결과를 Map으로 저장하고자 하면 Collector.toMap(키로 사용할 데이터를 리턴해주는 메소드, 매개변수 1개를 가지고 리턴하는 메소드)를 대입하면 됩니다.

앞의 메소드 결과로 key를 만들고 뒤의 메소드 결과를 value를 만듭니다.

 

=>toList()대신에 counting()을 설정하면 long타입의 데이터 개수를 리턴

=>summingIntsummingDouble메소드에 mapToIntmapToDouble을 대입하면 합계를 리턴

=>averagingInt averagingDouble메소드에 mapToIntmapToDouble을 대입하면 평균을 리턴

=>maxByminBy메소드에 비교하는 메소드를 대입하면 최대값이나 최소값을 리턴

최대나 최소는 실제 값이 아니고 최대값이나 최소값을 가진 데이터를 리턴

CollectorMain.java

public static void main(String[] args) {

               // 집계 함수를 사용

               // 글자가 5 이상이인 데이터의 개수를 파악

               // 샘플 데이터 작성

               Student student1 = new Student(1, "강좌진", "", 28, 98);

               Student student2 = new Student(2, "유관순", "", 19, 89);

               Student student3 = new Student(3, "김구", "", 38, 99);

               Student student4 = new Student(4, "안중근", "", 29, 100);

               Student student5 = new Student(5, "남자현", "", 25, 97);

 

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

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

 

               Stream<Student> stream = list.stream();

               //gender 값이 남인 데이터만 가지고 List 생성

               List<Student> manList= stream.filter((student)->{return student.getGender().equals("");}).collect(Collectors.toList());

               for(Student temp:manList) {

                      System.out.println(temp);

               }

              

               //gender 값이 여인 데이터를 가지고 name key 하고 전체를 value 하는 mAP 생성

               stream = list.stream();

               Map<String,Student> womanMap = stream.filter((student)->{return student.getGender().equals("");})

                             .collect(Collectors.toMap(Student::getName, (student)->{return student;}));

               //Map 모든 데이터 출력

               Set<String> keys = womanMap.keySet();

               for(String key : keys) {

                      System.out.println(key+" : " + womanMap.get(key));

               }

              

               //결과를 저장하는 것이 collector이다.

              

               System.out.println();

               stream = list.stream();

               long count = stream.filter((student) ->{return student.getGender().equals("");}).collect(Collectors.counting());

               System.out.println("여자 인원수 :" +count);

       }

 

10.grouping이 가능

=>collect 메소드에 Collectors.groupingBy()를 이용해서 그룹화가 가능

어떤 메소드의 결과로 그룹화 할 것인지를 설정하면 됩니다.

=>두번째 매개변수로 구하고자 하는 집계함수를 설정하면 그룹화 한 후 집계도 가능

counting(),averagingDouble(),maxBy(),minBy(), summingInt(),summingLong(), summingDouble()등으로 합계도 구할 수 있음

=>결과는 그룹화 하는 함수의 결과를 key로 해서 Map으로 리턴합니다.

=>데이터들만 규격화가 잘 되어 있다면 데이터베이스의 sql을 사용하는 것처럼 사용이 가능

 

11. 그룹화 실습

GroupingMain.java

public static void main(String[] args) {

               // 집계 함수를 사용

               // 글자가 5 이상이인 데이터의 개수를 파악

               // 샘플 데이터 작성

               Student student1 = new Student(1, "강좌진", "", 28, 98);

               Student student2 = new Student(2, "유관순", "", 19, 89);

               Student student3 = new Student(3, "김구", "", 38, 99);

               Student student4 = new Student(4, "안중근", "", 29, 100);

               Student student5 = new Student(5, "남자현", "", 25, 97);

 

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

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

              

               //List Stream으로 변환

               Stream<Student> stream = list.stream();

              

               //stream으로 그룹화

               Map<String,List<Student>> map =stream.collect(Collectors.groupingBy(Student::getGender));

               Set<String> keys = map.keySet();

               for(String key:keys) {

                      System.out.println(key +":" + map.get(key));

               }

              

               System.out.println();

              

               //스르팀은 한번 소모하면 소멸됩니다.

               //새로운 작업을 수행할 만다 스트림은 다시 생성

               stream = list.stream();

               //gender별로 그룹화   score 평균 구하기

               Map<String,Double> result = stream.collect(Collectors.groupingBy(Student::getGender,Collectors.averagingDouble(Student::getScore)));

               keys = result.keySet();

               for(String key:keys) {

                      System.out.println(key +":" + result.get(key));

               }

              

               System.out.println();

              

              

               stream = list.stream();

               //그룹화는 존재하는 메소드를 이용해도 되지만 람다로 직접 만들어도 됩니다.

               //하나의 매개벼수(스트림의 제너리) 받아서 데이터를 리턴하는 람다 식이면 됩니다.

               Map<String,Integer> result1 =

                             stream.collect(Collectors.groupingBy((student) ->{return student.getName();},

                                           Collectors.summingInt(Student::getScore)));

               keys = result1.keySet();

               for(String key:keys) {

                      System.out.println(key +":" + result1.get(key));

               }

              

               System.out.println();

              

               //성별 최대인 데이터를 추출

               stream = list.stream();

               Map<String,Optional<Student>> result2 =

                            stream.collect(Collectors.groupingBy(Student::getGender,

                                    Collectors.maxBy(Comparator.comparingInt(Student::getScore))));

               keys = result2.keySet();

               //Optional 출력할 Optional 함께 출력하기 때문에 이를 벗겨내기 위해서는 get()이나 orElse() 이용

               for(String key:keys) {

                      System.out.println(key +":" + result2.get(key).get());

               }

              

       }

 

12.병렬 스트림

=>java 1.8 이전 까지는 데이터의 모임에 병렬처리를 할려면 fork&join API 사용

API사용이 어려움

 

=>Stream api에서는 병렬 스트림을 만들기만 하면 자동으로 병렬 처리를 수행

스트림을 만들 stream()메소드 대신에 parallelStream()메소드를 호출하면 병렬 스트림이 됩니다.

Stream API 데이터 병렬성으로 구현

데이터들을 작은 데이터로 분할해서 작업하는 형태

 

=>작업의 병렬성

여러 작업의 요청이 작업들을 개별 스레드로 만들어서 병렬 처리하는 방식으로 서버가 대표적인 작업의 병렬성을 구현한 :

ParallelMain.java

// 문자열을 매개변수로 받아서 2 후에 출력하는 메소드

       public static void work(String str) {

               try {

                      Thread.sleep(2000);

                      System.out.println(str);

               } catch (InterruptedException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

               }

       }

 

       public static void main(String[] args) {

               String[] ar = { "", "", "", "", "" };

               List<String> list = Arrays.asList(ar);

 

               Stream<String> arStream = list.stream();

               // 일반 스트림을 생성해서 ar work 수행 - 10 정도 소요

               long start = System.currentTimeMillis();

 

               arStream.forEach((data) -> {

                      work(data);

               });

 

               long end = System.currentTimeMillis();

               System.out.println("순차 처리 :" + (end - start));

              

               //병렬 스트림을 생성해서 work 수행 -cpu 코더 개수에 따라 걸리는 시간이 다름

               //5 이상이여서 5개가 한번에 돈다.

               //코어가 5 이상이면 번에 수행하므로 2 =정도 소모

               //데이터 모임을 가지고 작업을 수행하는 경우 다른 영향을 전혀 받지 않고 수행되는 경우에는 병렬처리르 하는 것이 시간으로 이득

               //앞의 데이터의 연산결과를 가지고 다음 작업을 수행하는 작업은 병렬처리를 하는 것이 곤란

               //필터링 같은 경우는 병렬처리를 수행하기 좋은 작업 - 이러한 처리 방식을 Map - Reduce라고 합니다.

               //각각의 데이터에서 작업을 처리한 결과를 모아서 리턴

               Stream<String> paralleStream = list.parallelStream();

               // 일반 스트림을 생성해서 ar work 수행 - 10 정도 소요

               start = System.currentTimeMillis();

 

               paralleStream.forEach((data) -> {

                      work(data);

               });

 

               end = System.currentTimeMillis();

               System.out.println("순차 처리 :" + (end - start));

       }

 

 

 

**최근 언어의 자료형 구분

예전에는 value형과 reference형으로 구분(이것이 c언어일 경우)

수정 가능 여부에 따른 구분(mutableimmutable)

scalavector구분(데이터 개수를 구분)

null저장 가능 여부(OptionalnonOptional)(null을 저장할 수 있는 가 없는것인가)

객체지향언어에서  python에서 등에서는

a.b() ->이것하지 말라고 한다. .점이 있음녀 참조형이라고 한다. 데이터의 참조를 하고 있다가 찾아간다.

a null이고 None  nil => NullPointerException

그래서 참조형으로 할때 이렇게 쓰지 말라고 한다.

java에서는

if( a ! = null){ //null인지 확인한다.

           a.b();

}

참조형은 항상 null인지 물어봐야 한다.

optional : null저장 가능

NonOptional :null저장 못함

var a = new A();->NonOptional일경우 null체크 할 필요없다.

나누기 일 경우 문제가 생긴다. infinite등 문제 가 생긴다.

 

legacy - 전통적인 ,예전에 방식

 

변수를 선언할 때 뒤에 !를 붙이면 null저장가능

String temp; //에러 !표가 없기 때문에 그래서 값을 줘야 한다. => String temp ="Hello";//초기관을 설정하지 않으면 에러

String n! ;//초기값을 설정하지 않으면 null - 이 데이터는 사용할 때 null여부를 확인해야 합니다.

 

 

UML

시스템에 대한 지식을 찾고 표현하기 위한 언어

시스템을 개발하기 위한 탐구 도구

비주얼 모델링 도구

근거가 잘 정리된 가이드 라인

분석, 설계 작업의 마일스톤

실용적 표준

비주얼 프로그래밍 언어나 데이터베이스 표현도구 아님

개발 프로세스나 품질 보증 방안이 아님

 

가이드 라인이 있어서 작업할 때 편해진다.

base drived

파생 클래스

static은 밑줄을 건다. eclipse는 기울러져 있다.

 

보통 자료형을 쓰고 이름을 쓰는데

uml에서는 반대이다.

 

class A{

           String B ;//외부에서 받아서 사용했다.

}

List<String> ->string의 집한으로 이것이 aggregation이다.

 

Frame = new Frame():

Panel = new Panel();

 

Button = new Button();

button은 단독으로 만들 수 없다. buttondpanel이나 frame으로 해야 한다.

panelframe없으면 안된다.

frame아니면 보여질 수 없다.

 

Layout : container

widget 단독으로 사용불가

 

 

class의 상속 , interface..이다.

RectangularShape shape라는 interface 구현 한 것이다.

 

 

studentstudentiD CARD를 한계 가지고 있다.

대각선 적으로 바라봐야 한다.

 

분석  -> UML ->클래스 설계-> 구현

UML은 안하고 클래스 그냥 한다.

나중에는

분석  -> 클래스 설계-> 구현

설계 정보가 없다. 유지보수 할 경우 코드를 봐야 한다.

최근에는 역공학을 많이 사용한다. 나중에 하는 것이다.

eclipse에서 python이 가능하다.

eclipsevs code 조금 다르다.

vs code editor

eclipseid

python설치하고 설정해야 한다.

설치 다되면 ECLIPSE RESTART해야 된다.

그림파일이 만들어 질려면 체크해야 한다.

소스 코드 내부는 잘 안보고

상속이나 디자인 패턴이 잘 되여있는 지만 확인한다.

 

 

**디자인 패턴

Design Pattern

=>인스턴스의 사용용도에 따라 클래스의 모양을 만드는 것

GoF 디자인 패턴

runtime class의 생성자가 없다가 아니고 생성자가 안보인다. private로 만들어서 안보인다.

실글 패턴

보는 순간 실글 톤이고 인스턴스를 하나밖에 안된다.

날자를 설정할 경우 두개가 동시에 진행하면 안되서 하나가지고 순차적으로 해야 한다

entry point는 하나인게 좋다 그래야 제어가 쉽다.

1. 생성에 관련된 패턴

1)Singelton Pattern

=>인스턴스를 1개만 생성해서 사용하는 패턴

=>관리자 클래스(Controller)나 공유 데이터를 소유한 클래스 또는 서버에서 클라이언트의 요청을 처리하는 클래스 등에 적용

=>Java Server를 만들기 위한 FrameworkSpring은 기본적으로 클래스를 디자인해서 인스턴스를 만들면 Singelton Patternd으로 사용

 

 

python바이블인가 ? 이런것 봐야 한다.

jump to python

 

mainstatic으로 반든것이다 아무데에서도 부른 것이다.

메소드는 아무데에서나 부를 목적이고

변수는 하나만 만들어서 공유할 목적이다.

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-19  (0) 2020.10.10
java-18  (0) 2020.10.10
java-16  (0) 2020.10.10
java-15  (1) 2020.10.05
java-14  (0) 2020.10.04

+ Recent posts