반응형

**Design Pattern

=>객체의 사용 용도에 따라 클래스를 디자인하는 것

1. 생성과 관련된 패턴

1)Singleton

=>인스턴스를 1개만 만들 수 있도록 클래스를 디자인 하는 것

=>관리자 클래스(Controller, Manager)나 애플리캐이션 전체가 공유해야 하는 공유 데이터를 갖는 클래스 또는 서버에서 클라이언트의 요청을 처리하는 클래스 등은 일반적으로 인스턴스를 1개만 만들어서 사용

=>java.lang.Runtime클래스가 이 패턴으로 디자인

 

2)Decorator Pattern (커피)

=>외부에서 데이터를 주입받아 인스턴스를 생성하는 구조

=>하는 일은 유사한데 일을 수행해야 하는 대상이 여러가지 종류일 때 사용하는 패턴

=>작업을 수행하는 대상을 클래스 내부에서 직접 생성하지 않고 외부에서 생성한 후 주입받는 형태의 구조

=>java.io.BufferedReader클래스가 Decoragor Pattern의 대ㅍ적인 예

BufferedReader는 문자 스트림에서 문자열을 읽어오는 스트림

new BufferedReader(new InputStreamReader(new FileInputStream(String filepath))); 파일에서 읽어오기

new BufferedReader(new InputStreamReader(Socket.getInputStream())); 소켓에서 읽어오기

new BufferedReader(new InputStreamReader(HttpURLConnection.getInputStream())); 웹에서 읽어오기

                            

 

=>매개변수가 여러 개가 될 수 있습니다.

=>C++이나 JAVA는 생성자 오버로딩을 이용해서 구현하거나 매개변수로 대입되는 클래스의 다형성을 이용해서 구현

 

 

2.구조와 관련된 패턴

1)템플릿 메소드 패턴

=>메소드의 원형을 인터페이스(추상 클래스)에 선언하고 인터페이스를 구현한 클래스에 메소드를 구현하는 방식

c++은 인터페이스가 없고 추상클래스이다.

=>cc++(추상 클래스)는 인터페이스 대신에 헤더파일을 이용해서 구현

최근에는 이런 방식은 잘 사용되지 않음

 

스마트폰이나 게임해야 할때 조심해야 하는 부분

 

최근에 등장하는 GUI를 구현하는 언어들 중에도 파일을 2개로 나누어서 구현하는 경우가 있는데 이 경우는 디자인 파일과 구현 파일을 분리하는 형태잊 헤더 파일을 이용하는 형태가 아닙니다.

최근에는 INTERFACE, SWAFT등으로 작업한다.

 

=>프로그래밍을 할 때 사용자의 요청을 처리하는 클래스는 이 패턴으로 디자인 합니다.

이렇게 사용자의 요청을 처리하는 메소드를 소유한 클래스를 Service 클래스 라고 합니다.

데이터베이스 연동 프로그램에서 트랜잭션을 적용하는 지점은 Service 클래스의 메소드입니다.

 

=>어떤 Unit이라는 클래스를 설계하는데 사용자가 공격과 이동이라는 동작을 수행해야 합니다.

uml에서 확인

 

Interface mpl

classEx

int i

Controller controller =

소문자로 시작

변수

메소드

패키지

 

대문자로 시작

클래스

 

모두 대문자

상수

 

c언어 일 경우 macro는 대문자로 해라

numpy ndarray

pandas Series

python은 소문자로 시작했다 나중에 개발자들이 name을 사용하기 시작했다.

series() Series() 생성자

 

인터페이스 생성

//이 프로그램은 설계에 가깝다.

public interface Unit {

           //공격을 수행하는 메소드

           public void attack();

           //이동을 수행하는 메소드

           public void move();

           //자바는 코드로 도여있지만 uml로 하면 알기 쉽다.

}

 

인터페이스를 구현한 class를 생성

public class UnitImpl implements Unit {

 

           @Override

           public void attack() {

                       System.out.println("공격");

           }

 

           @Override

           public void move() {

                       System.out.println("이동");

           }

 

}

 

main메소드를 만들어서 사용

public class UnitMain {

           public static void main(String[] args) {

                       //탬플릿 메소드 패턴이 적용된 클래스의 인스턴스 만들기

                       //변수는 인터페이스 이름을 사용하고 생성자는 클래스 이름을 이용하는 형태로 많이 작성합니다.

                       UnitImpl unitImpl = new UnitImpl();

                       unitImpl.attack();

                       unitImpl.move();

                      

                       List<String> list = new ArrayList<String>();

           }

}

2)Adapter Pattern

=> 구현된 인터페이스를 이용해서 상속받은 클래스의 메소드를 호출하는 패턴

=>상속받은 클래스의 메소드를 직접 호출하기가 어려운 경우 이용

=>상속을 받았기 때무에 상위 클래스의 메소드를 호출해서 사용하는 것이 가능한데 상위 클래스의 메소드 이름을 다른 용도로 사용하는 경우 - 상위 클래스의 메소드의 내용을 변경해서 오버라이딩 하는 경우

=>원래 오버라이딩응ㄴ 상위 클래스의 메소드 기능을 확장하기 위해서 사용하는데 확장이 아니라 변경한 경우

 

=>Base 클래스 생성

public class OldSystem {

           public void process() {

                       System.out.println("예전 처리");

           }

}

 

=>Targe인터페이스 생성

public interface Target {

           //OldSystem process 를 호출하기 위한 메소드

           public void legacyProcess();

}

 

=>Derived 클래스 생성

public class NewSystem extends OldSystem implements Target{

           @Override

           public void process() {

                       //구현된 메소드의 오버러이딩 : 상위 클래스의 메소드를 호출하고 기능을 추가

                       /*

                       super.process();

                       System.out.println("기능 추가");

                       */

                       System.out.println("새로운 기능");

           }

           //java는 예전것도 지원한다.

 

           @Override

           public void legacyProcess() {

                       super.process();

           }

}

 

=>main메소드를 만들어서 실행

public class AdapterMain {

           public static void main(String[] args) {

                       NewSystem newSystem = new NewSystem();

                       //새로 만들어진 메소드

                       newSystem.process();

                       //이전에 만들어진 메소드

                       newSystem.legacyProcess();

           }

}

 

3)Composite Pattern

=>재귀적 구조를 쉽게 처리하기 위한 패턴

=>Recursive Call(Recursion- 함수가 내부에서 함수 자신을 다시 호출하는 경우)

=>파일 시스템에는 파일과 디렉토리가 있는데 디렉토리를 삭제할려고 하는 경우 디렉토리 안의 내용을 확인해서 디렉토리이면 다시 그 안에 있는 내용들을 삭제해야 합니다.

=>하나의 인터페이스를 만들고 인터페이스에 공통된 메소드 이름을 만들어주고 파일과 디렉토리 처리를 위한 클래스를 별도로 만들어서 처리하는 메소드를 구현합니다.

다형성을 구현하는 방식과 유사합니다.

 

=>인터페이스는 Entry- addremove그리고 rename

=>클래스는 FileDirectory로 생성

 

=>인터페이스 생성

//파일의 디렉토리 클래스에서 공통으로 사용할 메소드를 소유한 인터페이스

public interface Entry {

           public void add(Entry entry);

          

           void remove();//자기 자신을 지우는

          

           void rename(String name);

}

 

=>File클래스 생성

public class File implements Entry {

          

           //파일 이름을 저장할 변수

           private String name;

          

           public File(String name) {

                       this.name = name;//생성자로 부터 대입 받을 때

           }

          

           @Override

           public void add(Entry entry) {

                       System.err.println("파일에는 파일이나 디렉토리를 추가할 수 없습니다.");

           }

 

           @Override

           public void remove() {

                       System.out.println(name+"가 삭제 되였습니다.");

           }

 

           @Override

           public void rename(String name) {

                       this.name = name;

           }

 

}

 

=>Directory 클래스

public class Directory implements Entry {

           private String name;

          

           //FIle이나 Deriectory 를 소유할 수 있기 때문에 Entry를 여러 개 저장할 수 있는 자료구조를 소유

           List<Entry> list;

           public Directory(String name) {

                       this.name = name;

                       list = new ArrayList<Entry>();

           }

          

          

           @Override

           public void add(Entry entry) {

                       list.add(entry);

           }

 

           @Override

           public void remove() {

                       //list null이면 NullPointerException

                       //list가 인스턴스 생성은 되였는데 멤버가 없으면 수행을 안함

                       //Iterator 를 이용해서 데이터 접근

                       Iterator<Entry> iter = list.iterator();

                       while(iter.hasNext()) {

                                  Entry entry = iter.next();

                                  //file 은 지우지만 direcoty는 지우는 지 확인 해야 한다.

                                  entry.remove();

                       }

                       System.out.println("내부 데이터는 전부 삭제 되였습니다.");

                       /*for(Entry entry: list) {

                                  //디렉토리인지 확인해서 작업을 수행을 하지 않을 수 도 있습니다.

                                 

                                  //FIle이 있으면 File remove를 호출하고 Directory이면 Direcoty remove를 호출 - 다형성(Polymoriphism)

                                  //일반 다형성과 다른점은

                                  //Direcotory file를 할 수있다 .. .list가 있어서

                                  //이것 때문에 composite라고 한다.

                                  //file 은 지우지만 direcoty는 지우는 지 확인 해야 한다.

                                  entry.remove();

                       }*/

           }

 

           @Override

           public void rename(String name) {

                       this.name = name;

           }

 

}

 

=>main메소드를 만들어서 테스트

public class CompositeMain {

           public static void main(String[] args) {

                       File f1 = new File("파일1");

                       File f2 = new File("파일2");

                       File f3 = new File("파일3");

                      

                       Directory subDirectory = new Directory("하위 디렉토리");

                       subDirectory.add(f1);

                       subDirectory.add(f2);

                      

                       Directory superDirectory= new Directory("상위 디렉토리");

                       superDirectory.add(subDirectory);

                       superDirectory.add(f3);

                      

                       superDirectory.remove();

                      

                       //자료형 이름 출력

                       System.out.println(superDirectory.getClass().getName());

                       Entry entry = new Directory("디렉토리");

                       System.out.println(entry.getClass().getName());

           }

}

 

3.행동에 관련된 패턴

1)Command Pattern

=>처리 내용이 비슷한 명령을 모아서 실행하는 처리가 필요할 때 명령을 인스턴스로 취급해서 처리하는 패턴

 

=>데이터를 삽입하는 처리와 수정하는 처리가 필요한 경우

 

interface Action{

           public void execute(DTO dto); //다형성 구현한 것 처럼 한다.

}

 

class InsertAction Implement Action{

           public void execute(DTO dto){

                       오버라이딩 하고 삽입하는 크도

}

}

 

class updateAction Implement Action{

           public void execute(DTO dto){

                        수정하는 크도

}

}

 

//action에 대입되는 인스턴스 자체가 명령어와 유사한 역할을 수행

Action action = null;

if(command == 삽입){

           action = new insertAction();

}else if(command == 삭제){

           action = new updateAction();

}

action.execute(dto);

 

=>이러한 패턴은 서버의 Controller 클래스를 만들어서 요청에 따라 처리를 많이 사용

웹 서버 프로그래밍을 하다보면 URL에 따른 Routing구조를 만들 때도 이 구조를 이용합니다.

 

 

2)Observer Pattern

=>어떤 인스턴스의 내부 상태가 자주 변경되는 경우 내부 상태가 변경되는지를 감시하고 있다가 변경이 되면 알려줘서 처리를 할 수 있도록 해주는 패턴

=>알려준다고 해서 Notification이라는 표현을 많이 사용합니다.

=>이 패턴을 사용하는 대표적인 예가 스마트 폰의 뷰에서 키보드가 화면에서 보여지고 사라지는 것을 감시해서 뷰의 컴포넌트들을 재배치 하는 형태

 

3)Strategy Pattern

=>어떤 클래스가 공통된 부분이 있고 서로 다른 부분이 있는 경우 공통된 부분은 클래스 안에서 만들어 사용하고 서로 다른 부분은 외부에서 주입(Injection)받아 사용하는 패턴

public class Injection {

           private String common;//모든 인스턴스들이 "Java"라고 저장해서 사용

           private String diff1; //인스턴스들 마다 다름

           private String diff2; //인스턴스들 마다 다름

          

           public Injection(String diff1) {

                       common = "java";

                       //생성자를 이용한 주입

                       this.diff1  =diff1;

           }

          

           //diff2에 대한 setter메소드 - setter getter를 소유한 인스턴스 변수를 property라고 합니다.

           public void setDiff2(String diff2) {

                       this.diff2 = diff2;

           }

          

           //common diff1 null일 가능성이 없지만

           //diff2 setter 를 이용해서 대입받기 때문에 null일 가능성이 존재

           //서버 프로그래밍을 할 때는 메모리 부담이 되더라도 처음부터 만들어두고 사용하는 것이 좋고

           //클라이언트 프로그래밍을 할 떄는 속도가 느리더라고 필요할 때 생성하는 것이 좋습니다.

           //서버에서 하는 것인지 클라이언트 ㅎ하는 지 완전히 다르다ㅏ.r은 메모리 부담이 많이 된다.

           public void disp() {

                       System.out.println(common.toUpperCase());

                       System.out.println(diff1.toUpperCase());

                       System.out.println(diff2.toUpperCase());

           }

 

}

public class InjectMain {

           public static void main(String[] args) {

                       Injection injection = new Injection("JavaScript");

                       //다른 메소드들을 호출

                       //diff1을 가져고 다녀야 한다.

                      

                       //다른 메소드들을 호출              

                       injection.setDiff2("Spring");//사용하기 직전에 만들어서 사용한다. 메모리 절략은 되는데 속도가 느리다.

                       injection.disp();

                      

                       //setDiff2를 호출하지 않았기 때문에 diff2 null인 상태에서  toUpperCase를 호출해서 예외

                       injection = new Injection("FrontEnd");

                       injection.disp(); //java.lang.NullPointerException

           }

}

 

 

 

=>Design Pattern은 하나의 클래스에 여러가지를 적용하기도 합니다.

=>Design Pattern의 개념은 절대적인 개념이 아니라서 개발자마다 약간씩 다르게 설명하기도 합니다.

Singleton, Template Method, Command Pattern은 모두 동일하게 설명합니다.

=>이외에도 인스턴스 생성을 대신해주는 Factory Method Pattern이나 개발자가 만든 클래스에 코드를 더해서 실제로는 개발자가 만든 클래스와 다른 형태의 인스턴스를 만들어내느느 Proxy Pattern 등도 있습니다.

=>객체지향 프로그래밍에서는 디자인 패턴이 중요합니다.

 

객체지향 프로그래밍 언어 문법 -> 자료구조&알고리즘 ->디자인패턴 ->SW공학(개발 방법론 ..)

CCLASS가 없다. 디자인패턴이 없다.

 

 

**외부로 부터 데이터를 방아서 사용하는 경우

=>주입을 받는 방법은 생성자를 이용하는 방법이 있고 프로포티(setter)를 이용하는 방법

생성자를 이용하는 방법은 처음부터 가지고 있기 때문에 NullPointerException이 발생할 가능성이 적지만 메모리에 부담이 되고  setter을 이용하는 방식은 사용하기 전에 주입받아서 사용하기 때문에 메모리를 절약할 수 있지만 항상 NullPointerExcetpion에 대비해야 합니다.

 

**데이터 저장 및 읽기

1.로컬이나 원격에 Flat file형태로 저장

=>text 형식 : txt, csv형식 -용량이 작다는 장점이 있지만 전체가 아닌 일부 검색은 어려움

=>xml,json형식 : 구격화된 포맷 형식 - 인간이 알아보기 쉬움, 인간이 직접 작성도 가능,사이즈가 커지면 용량도 커지고 알아보기도 어려워집니다.

설정 내용을 저장할 때 나 실시간으로 작은 용량의 데이터를 주고받을 때 이용

 

2. 별도의 저장 프로그램 이용

=>Database:앞의 방법 들보다 보안이 우수하고 검색 조건을 다양하게 설정할 수 있음 , 데이터이외이 많은 것들을 저장해야 하기 때문에 오버헤드가 큼 (돈이 많이 든다.)

비밀번호 보안예기 많이 나온다.

 

 

**관계형 데이터베이스 인 오라클 사용

1.프로그래밍 언어에서 관계형 데이터베이스를 사용하는 방법

1)언어가 제공하는 기능만을 이용해서 구현 - java의 경우는 jdbc그리고 윈도우는 odbc

2)프레임워크를 이용해서 구형 - 언어가 제공하는 기능을 편리하게 사용할 수 있도록 만들어진 프레임워크 이용

-SQL Mapper: Java코드와 SQL을 분리해서 작성하는 구조 , Mybatis(iBatis가 예전 이름)(c#도 사용가능)가 대표적

=>성능은 떨어지지만 쉬워서 si(시스템 통합 - 기업의 전산화 , 외주를 많이 줌)에서 많이 사용

-Object Relation Mapper (ORM)

=>최근에 많이 사용하는 프레임워크로 하나의 행을 하나의 인스턴스와 매핑하는 프레임워크

하나의 테이블을 하나의 클래스와 매핑

데이터베이스에 대한 구조를 파악하고 있어야만 사용이 가능

어렵지만 성능이 우수해서 솔루션 제작에 많이 이용

JavaJPA(구현체로는 Hibernate)가 대표적인 프레임워크 - 다른 언어에도 대부분 있음

카카오와 배민이 이것 사용하고 있다.

sql없이 데이터베이스 작업이 가능 - dbms를 변경해서 적용하더라고 설정파일만 수정하면 됩니다.

 

 

iBatis, MyBatis

MariaDB, MySQL

Fedora(테스트형), Cent OS(stable버전), Red Hat Enterprise(stable해서 사용화 버전 ) <->Ubuntu

 

sqlite ->autoincrement : sqlite의 일련번호

오라클 ->sequence nextval()

 

서비스를 작은 마이크로 서비스 단위로 만들고

 

2.java에서 관계형 데이터베이스 연동 방법

1)사용하고자 하는 데이터베이스와의 인터페이스를 제공하는 드라이버를 사용할 수 있도록 설정

=>자바는 드라이버를 build path에 추가하고 클래스를 로드

 

 

드라이브 사용하는 것은 프린트 서로 다른 것 통신해주기로 해서

python은 예외 sqlite3가 예외이다 드라이브에 lib에 있어서 할 필요없다.

pip install

 

2)데이터베이스 접속 정보를 가지고 데이터베이스 연결 객체(java.sql.Connection)를 생성

=>접속정보는 데이터베이스 URL, 포트번호 , 데이터베이스이름(오라클의 경우는 SID또는 serviceName)이 필요하고 접속계정과 비밀번호도 필요

=>데이터베이스 종류에 따라서 접속 계정과 비밀번호가 필요없는 경우가 있음

=>데이터베이스 중에는 자신의 기본 포트를 사용하는 경우 포트번호 생략이 가능(Mysql3306 포트인 경우 생략가능 )

=>자바의 경우는 연결 객체를 이용해서 트랜잭션 사용 방법을 설정합니다.

 

3)Connection을 이용해서 SQL을 주고받을 객체를 생성하고 실행 - JavaStatement(완성된 sql) ,PreparedStatement(나중에 데이터를 매핑할 수 있는 sql - 대부분의 언어가 사용), CallableStatement (Procedure 실행)

 

4)결과를 사용

-select 를 제외한 구문 : 영향받은 행의 개수를 정수로 리턴

- select 구문 : select의 결과를 사용할 수 있는 Cursor를 리턴

 

5)트랜잭션 처리를 하고 사용한 객체를 close를 합니다.

 

6)java에서는 이 과정 전체가 예외처리를 강제합니다.

다른 언어에서 예외처리를 강제하지 않더라도 예외처리를 해주는 것이 좋습니다

문제가 발생하면 어떤 조치를 취할 수 있도록 해 주어야 합니다.

데이터베이스는 외부에 존재하는 경우가 많기 떄무에 어떤 문제가 발생할 지 우리가 예측할 수 없습니다.

 

3.애플리케이션 프로그램이 잘 수행하지 않는 sql

=>Grant(권한 부여), Revoke(권한 회수)

=>Create(개체 생성) ,Alter(개체 구조 변경), Drop(개체 삭제) ,Truncate(테이블의 데이터만 삭제), Rename(테이블의 이름 변경)

=>주로 관리자가 사용하는 sql명령들이고 이 명령들은 Rollback이 안됩니다.

관리자만 로컬에서 사용하는 애플리케이션을 만들어서 수행하도록 하는 경우는 종종 있습니다.

(원격으로 잘 안한다.)

 

4.데이터베이스 계정

ip: 

PORT:1521

SID:xe

계정 : user01-user30

비번 : user01-user30

 

강사님 계정 user00

 

5.샘플 테이블을 생성

=>Oracle의 자료형

숫자는 - number(정수자릿수),number(전체자릿수 ,소수자릿수)

 

문자열 - char(글자수),varchar2(글자수), clob

한글은 곱하기 3

char를 사용하면 글자수보다 작은 양의 글자를 입력하면 뒤에 공백이 있습니다.

clob는 아주 많은 글자인 경우 사용

 

날짜 - date

 

=>거래정보 테이블

거래번호 - 정수이고 기본키, 일련번호 형식

품목코드 - 거래한 품목의 코드 , 문자열 20자리

품목명 - 거래한 품목이름 , 문자열  100자리

단가 - 정수 7자리

수량 - 정수 3자리

거래일 - 날짜

거래 id -거래한 유저의 id, 문자열 50자리

 

create table transactions(

           num number(10) primary key,

           itemcode varchar2(20),

           itemname varchar2(100),

           price number(7),

           cnt number(3),

           transdate date,

           userid varchar2(50)

);

 

6. 프로젝트를 생성하고 오라클을 사용할 준비

=> 데이터베이스 드라이브를 프로젝트의 build path애 추가

오라클은 ojdbc>.jar

ojdbc6.jar :숫자의 의미는 자바 버전이고 이 이외의 숫자가 추가로 있으면 오라클 버전입니다.

상위버전은 하위버전을 지원

 

7.애플리케이션이 시작될 때 1번 드라이버 클래스를 로드

=>Class.forName("드라이버 클래스 이름"); //여기에 직접 쓰지 않는다.

=>실제 애플리케이션을 만들 때는 드라이버 클래스 이름을 별도의 파일에 작성하고 읽어들이는 구조로 만듭니다.

=>오라클의 경우 드라이버 클래스 이름: oracle.jdbc.driver.OracleDriver

=>드라이브 클래스 이름이 틀리거나 jar파일을 build path에 추가하지 않았다면 예외가 발생합니다.

public class OracleMain {

           public static void main(String[] args) {

                       try {

                                  //이 코드는 애플리케이션 전체에서 1번만 수행하면 됩니다.

                                  Class.forName("oracle.jdbc.driver.OracleDriver");

                                  System.out.println("드라이브 클래스 로드 성공");

                       } catch (Exception e) {

                                  System.out.println(e.getMessage());

                                  e.printStackTrace();

                       }

           }

}

 

8. 데이터베이스 연결 및 해제

=>데이터베이스에 연결할 때 는 3가지 정보가 필요

데이터베이스 url:  데이터베이스 종류마다 설정 방법이 다름

계정

비번

=>계정과 비번은 없어도 되는 경우가 있습니다.

=>오라클의 url: -jdbc:oracle:thin:@IP또는 domain :port:sid

sid가 아니고 serviceName인 경우는 : 대신에 /serviceNmae

 

=>데이터베이스 접속

Connectioin ? = DriverManager.getConnection(url, id, pw);

 

=>데이터베이스 접속 해제

?.close();

 

=>url이 잘못 된 경우는 기본적인 접속시간동안 접속을 해보고 네트워크 문제라고 예외를 발생시킵니다.

=>idpw가 잘못된 경우는 login denied라는 예외를 발생시킵니다.

           public static void main(String[] args) {

                       try {

                                  //이 코드는 애플리케이션 전체에서 1번만 수행하면 됩니다.

                                  Class.forName("oracle.jdbc.driver.OracleDriver");

                                  System.out.println("드라이브 클래스 로드 성공");

                                 

                                  //데이터베이스 접속

                                  Connection con = DriverManager.getConnection("jdbc:oracle:thin:@ip주소:1521:xe","user29","user29");

                                  //ip주소 잘못되면 멍때리고 있다.후에 나온다.

                                  //포트번호가 틀리면 빨리 떤다.

                                  //login denined

                                  System.out.println("접속 성공");

                                 

                                  //접속 해제

                                  con.close();

                       } catch (Exception e) {

                                  System.out.println(e.getMessage());

                                  e.printStackTrace();

                       }

           }

 

9.데이터베이스 드라이버이름이나 접속 정보는 별도로 작성한 후 읽어 들이는 구조로 만드는 것을 권장

개발환경과 운영환경이 다를 가능성 때문입니다.

 

프로그래밍 언어별 실행방법

1. 줄 단위로 읽어가면서 실행 - 인터프리터 방식

(대표적인 언어가 python)

python은 코드를 작성할 때 한줄 씩 실행한다.idle에서는 줄단위로 해서 불편해서 파일로 실행한다.

 

 

2.소스 전체를 번역한 후 실행

1).줄단위로 실행

 

2).전체로 한꺼번에 실행

 

 

source code -> compile(번역) -> java에서는 byte code(중간코드)만든다. -> build -> 실행 가능한 코드가 만들어진다. -> 로드 (메모리에 적재) -> 실행 (Run)

 

                

개발 환경 -------------------------------------> 운영환경

localhost:1521 : xe                         211....:1521 : xe

getConnection("localhost:1521:xe")=>이것을 운영에 올릴 때

=> getConnection("211..:1521:xe")으로 소스 코드 바꿔야 한다.

소스 코드 바꾸면 처음 부터 해야 한다.

예기치 않는 문제가 발생

이런 경우를 줄이려면 이쪽에 작업을 안할려고 하는 방법

setting.xxx=>파일 을 만들어서 db : localhost: 1521:xe

getConncetion(파일의 내용을 읽는 코드를 사용)

데이터를 바꿀 경우 파일의 내용을 바꾸면 된다. 자바 코드를 바꾸지 않았다.

BUILD를 다시 할 필요없다. 배포만 다시 하면 된다.

SETTING.XXX-> properties

xml -> json

자원이 넉넉하면 클릭해서 손을 댈 수 있어서 별도에 디비에 여는 경우가 있다.

별도의 디비에 작성

 

 

 

반응형

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

java-20  (0) 2020.10.10
java-19  (0) 2020.10.10
java-17  (0) 2020.10.10
java-16  (0) 2020.10.10
java-15  (1) 2020.10.05
반응형

**스트림 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