|  HashSet<int[]>와 Hashset<ArrayList<Integer>>

문제를 풀다보면, 좌표를 집합에 넣어야 하는 경우가 있었다.

예를 들어, (0, 1), (2, 1) 

그래서 아무 생각 없이 아래와 HashSet<int[]>를 쓰게 되면 contains를 할 때 검색이 제대로 되지 않는 걸 볼 수 있다.

 

왜 그럴까?

 

이유는 배열의 경우 Hashcode를 비교하고, 

리스트의 경우 Wrapper된 Integer값을 비교하기 때문.

HashSet<int[]> int 배열의 hashcode를 비교
HashSet<ArrayList<Integer>> Integer List의 Wrapper객체(Integer)를 비교

 

따라서, 좌표와 같은 수열의 집합을 만든다고 하면 HashSet 안에 ArrayList로 넣는 것이 좋다.

 

[ 참고 ]

https://stackoverflow.com/questions/65454683/check-if-an-array-exists-in-a-hashsetint

'Computer Science > Algorithm' 카테고리의 다른 글

[알고리즘] 그리디  (0) 2022.08.25
[알고리즘] 탐색 - DFS, BFS, 이진 탐색  (0) 2022.08.25
[알고리즘] 정렬  (0) 2022.08.11
[알고리즘] 알고리즘 개요  (0) 2022.08.09
[백준 11660] 구간 합 구하기 5  (0) 2022.07.14

|  CRUD

- 소프트웨어가 가지는 기본적인 데이터 처리 기능

- CRUD는 MariaDB/MySQL, ORACLE 모두 동일한 문법을 사용하는 것으로 확인됐다. (아래 코드 비교)

구분 의미 SQL REST API WHERE 필수
CREATE 삽입 INSERT PUT/POST X
READ 조회 SELECT GET X
UPDATE 갱신 UPDATE PUT/PATCH O
DELETE 삭제 DELETE DELETE O
-- CRUD
-- INSERT
INSERT INTO bootcamp_member2
(name, email, mobile_no, password, marketing_yn, register_date)
VALUES
('테스트3', 'test3@gmail.com', '01022223212', '2222', true, now());

-- SELECT : WHERE 선택 (대다수 WHERE 사용)
SELECT *
FROM bootcamp_member2
WHERE marketing_yn = true
  AND name = '테스트3';

-- UPDATE : WHERE 필수
UPDATE bootcamp_member2
SET marketing_yn = false
WHERE name = '김길동';

-- DELETE : WHERE 필수
DELETE FROM bootcamp_member2
WHERE email = 'kim123@gmail.com';

 

1.  데이터 삽입(INSERT)

🐱 단순 데이터 추가

- 아래와 같이 단순 데이터를 추가할 경우, 데이터가 없을 때(NULL) 문제가 발생할 수 있다.
- 회원가입을 예로 들었을 때, 어떤 MEMBER의 ID는 유일해야한다. --> 데이터 입력에 대한 제약이 필요
- 여기서 제약 조건이 필요해진다.
  * 제약조건(Constraint) : 특정 데이터에 대해 거는 제약

📡 MariaDB

INSERT INTO 테이블명
(칼럼명, 칼럼명, 칼럼명....)
VALUES
(값, 값, 값...);

-- 예시
INSERT INTO bootcamp_member
(name, email, mobile_no, password, marketing_yn, register_date)
VALUES
('홍길동', 'simDev1234@gmail.com', '01011111111', '1234', true, now());
더보기

📡 Oracle

INSERT INTO MEMBER(ID, PWD) VALUES('NEW LEC','111');
INSERT INTO MEMBER(ID, PWD) VALUES('DRAGON','111');

🌈 인코딩 문제 해결

- 테이블에 Insert를 하려고 보니 아래와 같은 오류가 나타났었다.

Incorrect string value: '\xED\x99\x8D\xEA\xB8\xB8...' for column ~~~~~~~~

- 내용을 쭉 읽어보니까 위 'name' 칼럼의 한글이 깨져서여서(인코딩 문제) 정확한 원인과 해결 방법을 찾았는데

  - 원인 : DB의 디폴트 인코딩 방식 (default_character_set_name)이 utf8이 아니여서였다.

select schema_name, default_character_set_name from information_schema.schemata;
+--------------------+----------------------------+
| schema_name        | default_character_set_name |
+--------------------+----------------------------+
| information_schema | utf8mb3                    |
| mysql              | latin1                     |
| performance_schema | utf8mb3                    |
| sys                | utf8mb3                    |
| testdb1            | latin1                     |
+--------------------+----------------------------+

  - 해결 : 아래와 같이 db의 인코딩 방식과, 테이블의 인코딩 방식을 변경하면 된다.

  * 한 번 셋팅된 테이블 인코딩 방식은 db 인코딩 방식을 변경해도 유지되므로 꼭 table도 변경해야한다.

alter database 디비명 default character set utf8;
alter table 테이블명 convert to character set utf8;

 

🐱 제약조건을 통한 INSERT

- 아래에서는 제약조건으로 pk를 예시로 들었다.
- 제약조건에 대한 자세한 내용으로는 [더보기]를 참고하면 자세한 내용이 들어있다.

📡 MariaDB

alter table bootcamp_member2 add constraint primary key pk_bootcamp_member2(email);

 

2.  데이터 조회(SELECT)

(1) 선택적 조회 : WHERE절을 쓰자
- 일반적으로 회사에서 데이터를 조회할 때는, 전체 조회를 하지 않는다.
  데이터 양이 방대하기 때문에 컴퓨터나 너무 느려질 수 있기 때문
- 따라서, WHERE절이 필수는 아니라도 함께 써주는 것이 좋다.

(2) and 나 or를 통해 추가적인 조건사항을 걸 수 있다.

- 아래의 코드처럼, where절을 통한 조건을 걸 때 and나 or를 통해 추가 조건을 걸 수 있다.

📡 MariaDB

-- 전체 조회
select *
from 테이블명
;

-- 선택 조회
select 
  name, email
from 테이블명
;

-- where절 조건
select *
from 테이블명
where 조건
   or 조건
;
더보기

📡 Oracle

-- 전체 조회
select * 
from 테이블명
;

-- 선택 조회
select 
   name, kor, eng, mat, prev
from 테이블명
;

 

3.  데이터 갱신(UPDATE)

(1) WHERE절을 필수로 사용해야 한다.
- 그렇지 않은 경우 전체 데이터가 모두 갱신된다.

(2) 여러개의 칼럼을 동시에 갱신할 수 있다.

📡 MariaDB

update 테이블명
set
    변경할 칼럼의 데이터
where 조건
;
더보기

📡 Oracle

update 테이블명
set 
   변경할 칼럼의 데이터
where 조건

 

4.  데이터 삭제(DELETE)

(1) WHERE절을 필수로 사용해야 한다.
- 그렇지 않은 경우 전체 데이터가 모두 삭제된다.

(2) 데이터를 삭제할 때는 주의를 요한다.

📡 MariaDB

delete from 테이블명
where 조건;
더보기

📡 Oracle

delete from scores 
where name = '바길동';

delete from scores 
where 1 = 1; -- 전체 데이터 삭제

 

 

[ 출처 및 참고 ]

- 부트캠프 수업 내용을 들은 후 정리한 내용입니다.

- 과거에 정리했던 내용과 함께 정리

https://why-dev.tistory.com/73?category=958782 

|  테이블 정의

- 정형화된 데이터는 RDBMS의 기본 단위인 Table 형태로 저장된다.

- Table은 관계(Relation)라고도 불리며, 특정 종류의 데이터를 구조적으로 묶은 목록을 말한다.

  (1) 칼럼 = 필드 = 속성         : 변수 EX. email, name, addr...

  (2) 로우 = 레코드 = 튜플     : 실제 값 EX. kim1234@gmail.com, kim1235@gmail.com...

 

|  데이터 자료형

- 종류 : 숫자 / 문자 및 문자열 / Boolean / 날짜 및 시간 / 큰 객체 

- 각 DBMS마다 자료형을 표현하는 방식에 차이가 있다.

  Oracle MySQL/MariaDB SQL Server PostgreSQL
숫자 NUMBER
FLOAT
TINTINT
SMALLLINT
MEDIUMINT
INT
BIGINT
DECIMAL
FLOAT
DOUBLE
BIGINT
INT
SMALLINT
TINYINT
NUMERIC/DECIMAL
FLOAT
REAL
SMALLINT
INTEGER
BIGINT
DECIMAL
NUMERIC
REAL
DOUBLE
문자(열) CHAR
VARCHAR2
CHAR
VARCHAR
CHAR
VARCHAR
CHAR
VARCHAR
Boolean   BIT BIT BOOLEAN
날짜/시간 DATE
TIMESTAMP
DATE
TIME
DATETIME
TIMESTAMP
YEAR
DATE
DATETIME
DATETIME2
SMALLDATETIME
TIME
DATE
TIME
TIMESTAMP
큰 객체 LONG
CLOB
BLOB
TEXT
MEDIUMTEXT
LONGTEXT
BLOB
TEXT
BINARY
IMAGE
TEXT

 

|  테이블 생성/삭제/조회

A. DDL을 통한 테이블 생성과 삭제

📡 MariaDB

-- 테이블 생성
CREATE TABLE EVENT_INFO(
    START_DATE DATETIME,
    END_DATE DATETIMEl,
    SUBJECT VARCHAR(255),
    CONTENTS TEXT
);

-- 테이블 삭제
DROP TABLE EVENT_INFO;
더보기

📡Oracle

CREATE TABLE MEMBER
(
    ID       VARCHAR2(50),
    PWD      VARCHAR2(50),
    NAME     VARCHAR2(50),
    GENDER   CHAR(50),
    AGE      NUMBER,
    BIRTHDAY CHAR(50),
    PHONE    CHAR(50),
    REGDATE  DATE
)

DROP TABLE MEMBER;

☝️ 테이블 명명규칙 ☝️

- 일반적으로 DB 테이블 또는 DB 칼럼명대문자 스네이크 기법을 사용한다.

- pf. 과거 컴퓨터 속도가 느리던 시절 아스키 코드의 앞자리에 해당하는 대문자코드를 선호 

- pf. 회사마다 차이가 있을 수는 있다.

CREATE TABLE BOOTCAMP_MEMBER(

);

 

B. 데이터베이스 툴을 통해 테이블 생성(DataGrip기준)

더보기

|  데이터베이스 툴

- DBMS를 편리하게 사용할 수 있도록 하는 IDE툴이다.

- DataGrip이 가장 많이 사용되며, DBeaver 또한 자주 사용된다.

- 종류 : DataGrip, DBeaver, MySQL WorkBench, SQL Developer, 그 외 (Toad, SQLGATE 등...)

 

|  데이터베이스 툴 설치

(1) DataGrip 설치

https://dbeaver.io/download/

(2) DBeaver 

https://www.jetbrains.com/ko-kr/toolbox-app/ 

 

|  데이터베이스 툴 실행

- 필요 정보 : IP주소, port번호, database(instance) 이름, 계정명, 비밀번호

- 사용하는 DBMS에 맞추어 위 필요정보를 입력한 후 ping을 통해 연결 확인

- [tables] - 우측마우스 - Table 생성

- DDL script를 자동으로 생성해준다.

- 대체로 대다수의 데이터베이스 툴이 이와 비슷한 기능을 제공한다.

⭐️ Tip : [tables] - 우측마우스 - [SQL script] - [원본 DDL 복사] 로 SQL테이블을 그대로 복사할 수 있다.

 

C. 테이블 조회

📡 MariaDB

SHOW TABLES;
-- 또는
SELECT *
FROM 테이블명

 

 

[ 참고 및 출처 ]

부트 캠프 강의를 들은 후 정리한 내용입니다.

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=on21life&logNo=221548738367 

 

|  개요

📌  인스턴스란? = database(데이터의 집합) = table space = 테이블이 위치하는 공간(디렉토리)
📌  계정은 왜 여러개 생성할까? 접속자마다 DB 관리권한이 다를 수 있다. 
📌  원격으로 접속하는 컴퓨터에 대한 접속권한도 고려해야 한다.

📌  SQL명령어 - DDL, DML, DCL

 

|  SQL (Structured Query Language)

- 의미 : DBMS와 소통하기 위한 구조화된 질의어

- 구분

데이터 정의어(DDL, Data Definition Langugae) CREATE, DROP, ALTER, TRUNCATE
데이터 조작어(DML, Data Manipulation Language) INSERT, UPDATE, DELETE, SELETE ( CRUD )
데이터 제어어(DCL, Data Control Language) GRANT, REVOKE, TRANSACTION, COMMIT, ROLLBACK..

☝️  데이터 정의어 : 테이블과 인덱스 구조를 관리

✌️  데이터 조작어 : DDL를 통해 테이블 구조가 잡히면 그 안에 넣을 데이터를 CRUD하는 언어

🤟 데이터 제어어 : 권한을 부여하거나 뺏는 등의 제어와 관련된 언어

 

|  데이터베이스 인스턴스 및 계정 생성 

A. 데이터베이스 생성과 삭제

📡 MariaDB

CREATE DATABASE /*테이블명*/;
DROP DATABASE /*테이블명*/;
더보기

📡Oracle

// 아래와 같이 테이블스페이스를 만들지 않으면 System(관리자=root)와 같은 공간 공유
DEFAULT TABLE SPACE USERS 기본테이블 스페이스;
TEMPORARY TABLESPACE 임시테이블 스페이스;

 

B. 데이터베이스 계정 생성

📡 MariaDB

- 데이터베이스 계정 조회

show databases;
use mysql;
select User, Host, Password from user;

- 계정 생성하기

CREATE USER '계정명'@'호스트명' IDENTIFIED BY '비밀번호';
CREATE USER '계정명'@'localhost' IDENTIFIED BY '비밀번호'; // 로컬만 허용
CREATE USER '계정명'@'%' INDENTIFIED BY '비밀번호'; // 다른 ip도 허용

flush privileges;

rf. 원격 계정 접속 : 로그인 옵션에 [ -h  ip주소 ]를 추가한다.

 

// 원격 pc에서
mysql -h /*접속하려는 ip*/ -u /*계정명*/ -p /*비밀번호*/

 

C. 데이터베이스 계정 권한 설정

📡 MariaDB

- 계정에 테이블에 대한 사용 권한을 부여하는 것이다.

GRANT ALL PRIVILEGES ON 테이블명.* TO '계정명'@'호스트명' IDENTIFIED BY '비밀번호'; // 특정 IP
GRANT ALL PRIVILEGES ON 테이블명.* TO '계정명'@'%' IDENTIFIED BY '비밀번호'; // 전체 IP 대상

FLUSH PRIVILEGES; // 권한 설정사항 FLUSH
더보기

📡 Oracle

> 관리자 아이디로 접속 후
> 권한 부여
grant all                        --- 모든 권한 부여(위험)
grant connect to 계정            --- db 연결 권한
grant resource to 계정           --- db 자원(table, sequence) 생성 권한
grant dba to 계정                --- 시스템 자원 무제한 사용, 다른 사용자 권한 조정 등 강력한 기능에 관한 권한
grant select on 테이블 to 계정   --- 조회(SELECT) 권한 부여
grant create view to 계정        --- 뷰 권한 

> 권한 회수
revoke connect,resource from 계정
revoke select on 테이블 또는 뷰명 from 계정  -- 테이블 또는 뷰 권한 회수

 

D. 데이터베이스 조회

📡 MariaDB

SHOW DATABASES;
더보기

📡 Oracle

SELECT *
FROM ALL_ALL_TABLES;

 

 

[ 참고 및 출처 ]

부트 캠프 강의를 들은 후 정리한 내용입니다.

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ragew&logNo=30047111788 

https://sgcomputer.tistory.com/247

|  컬렉션이란?

- 자바에서 자료구조를 구현한 클래스를 말한다.

- 컬렉션을 추상적으로 구분한 분류는 크게 아래와 같다.

- 단, 실제 Collection을 상속하는 건 List와 Set, Queue이며 Map은 별도의 인터페이스이다.

- Collections를 통해서 List를 정렬할 수 있으며,

  Set이나 Map의 경우 TreeSet과 TreeMap을 쓰면 data가 정렬되어 저장된다.

구분 하위 클래스 중복 순서
List ArrayList, LinkedList, Vector, Stack(Vector 상속) o o
Set HashSet, LinkedHashSet, TreeSet x -
Map Hashtable, HashMap, LinkedHashMap, TreeMap key x, value o -

 

|  List / Set / Map 코드

import java.util.*;

public class CollectionTest {
    public static void main(String[] args) {

        // Collections
        // ㄴ List, Set, Queue가 상속 / Map은 별도

        // 1. List
        // : 순서대로 데이터를 저장하기 위한 리스트 (중복o, 순서o)
        // : ArrayList, LinkedList, Vector, Stack(Vector 상속)

        // A. ArrayList
        // 순차적인 추가/삭제는 빠르나 중간에 데이터를 추가/삭제하게 되면 linkedList보다 느리다.
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(4);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(1);
        System.out.println("arrayList = " + arrayList);

        // B. LinkedList
        LinkedList<Integer> linkedList = new LinkedList<>();
        linkedList.add(4);
        linkedList.add(2);
        linkedList.add(3);
        linkedList.add(1);
        linkedList.add(2);
        linkedList.add(1);
        System.out.println("linkedList = " + linkedList);

        // 2. Set
        // : 중복을 제거하기 위해 사용한다. 수학의 집합과 연관되어 있다. (중복x)
        // : HashSet, LinkedHashSet, TreeSet

        // A. HashSet
        // - 항상 데이터가 정렬되지 않지만 대체로 정렬되어 나옴 (정렬x, 저장순서 유지x)
        System.out.print("hashSet : ");
        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(4);
        hashSet.add(2);
        hashSet.add(3);
        hashSet.add(1);
        hashSet.add(2);
        hashSet.add(1);

        Iterator<Integer> hashSetIterator = hashSet.iterator();
        while (hashSetIterator.hasNext()) {
            System.out.print(hashSetIterator.next() + " ");
        }
        System.out.println();

        // B. LinkedHashSet : HashSet를 상속한다.
        // - 기존 데이터의 저장순서가 그대로 유지된다. (정렬x, 저장순서 유지O)
        System.out.print("linkedHashSet : ");
        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(4);
        linkedHashSet.add(2);
        linkedHashSet.add(3);
        linkedHashSet.add(1);
        linkedHashSet.add(2);
        linkedHashSet.add(1);

        Iterator<Integer> linkedHashSetIterator = linkedHashSet.iterator();
        while (linkedHashSetIterator.hasNext()) {
            System.out.print(linkedHashSetIterator.next() + " ");
        }
        System.out.println();

        // C. TreeSet
        // - 데이터가 정렬이 되어 출력된다. (정렬O, 저장순서 유지x)
        System.out.print("TreeSet : ");
        TreeSet<Integer> treeSet = new TreeSet<>();
        treeSet.add(4);
        treeSet.add(2);
        treeSet.add(3);
        treeSet.add(1);
        treeSet.add(2);
        treeSet.add(1);

        Iterator<Integer> treeSetIterator = treeSet.iterator();
        while (treeSetIterator.hasNext()) {
            System.out.print(treeSetIterator.next() + " ");
        }
        System.out.println();

        // 3. Map
        // : key 과 value가 entry 형태로 저장된다. (Entry가 Map의 내부 인터페이스다)
        // : Hashtable, HashMap, LinkedHashMap, TreeMap

        // A. HashMap
        // : HashTable과 HashMap은 사용면에서 비슷한데 차이점은 아래와 같다.
        // : Hashtable은 Thread-safe & key에 null미사용, HashMap은 Thread-safe X & key에 null사용
        // - 데이터가 정렬되지 않은 상태로 출력된다 (정렬x, 저장순서 유지x)
        System.out.println("=== HashMap === ");
        HashMap<String, Integer> hashMap = new HashMap<>();
        hashMap.put("고객3", 1000);
        hashMap.put("고객2", 2000);
        hashMap.put("고객1", 3000);
        hashMap.put("고객0", 4000);

        for (String key : hashMap.keySet()) {
            System.out.println(key + ":" + hashMap.get(key));
        }

        // B. LinkedHashMap
        // - key 데이터의 저장 순서가 유지된다. (정렬x, 저장순서 유지o)
        System.out.println("=== LinkedHashMap === ");
        LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("고객3", 1000);
        linkedHashMap.put("고객2", 2000);
        linkedHashMap.put("고객1", 3000);
        linkedHashMap.put("고객0", 4000);

        for (String key : linkedHashMap.keySet()) {
            System.out.println(key + ":" + linkedHashMap.get(key));
        }

        // C. TreeMap
        // - key 데이터가 정렬된다 (정렬o, 저장순서 유지x)
        System.out.println("=== TreeMap === ");
        TreeMap<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("고객0", 1000);
        treeMap.put("고객1", 2000);
        treeMap.put("고객2", 3000);
        treeMap.put("고객3", 4000);

        for (String key : treeMap.keySet()) {
            System.out.println(key + ":" + treeMap.get(key));
        }

        // - Tip : TreeMap의 key 데이터를 내림차순으로 저장하려면?
        System.out.println("=== TreeMap Reverse === ");
        treeMap = new TreeMap(Comparator.reverseOrder()); // new TreeMap(Comparator)
        treeMap.put("고객0", 1000);
        treeMap.put("고객1", 2000);
        treeMap.put("고객2", 3000);
        treeMap.put("고객3", 4000);

        for (String key : treeMap.keySet()) {
            System.out.println(key + ":" + treeMap.get(key));
        }
    }
}

>> 결과

arrayList = [4, 2, 3, 1, 2, 1]
linkedList = [4, 2, 3, 1, 2, 1]
hashSet : 1 2 3 4 
linkedHashSet : 4 2 3 1 
TreeSet : 1 2 3 4 
=== HashMap === 
고객2:2000
고객1:3000
고객3:1000
고객0:4000
=== LinkedHashMap === 
고객3:1000
고객2:2000
고객1:3000
고객0:4000
=== TreeMap === 
고객0:1000
고객1:2000
고객2:3000
고객3:4000
=== TreeMap Reverse === 
고객3:4000
고객2:3000
고객1:2000
고객0:1000

 

|  Collections.sort

import java.util.*;

class Customer implements Comparable<Customer>{
    private int no;
    private String name;

    public Customer(int no, String name) {
        this.no = no;
        this.name = name;
    }

    @Override
    public int compareTo(Customer o) {
        return this.no - o.no;
    }

    public void print() {
        System.out.println(this.no + "=" + this.name);
    }
}

public class CollectionsSortTest {
    public static void main(String[] args) {
        // Collection에서 Sort를 하는 방식
        
        // A. List를 정렬할 경우 - Collections.sort(List);
        // : 오직 List의 경우에만 Collections.sort()를 쓸 수 있다.
        // : Map의 Set의 경우 TreeMap, TreeSet을 쓰는 것이 좋다.
        List<Integer> list = new ArrayList<>(Arrays.asList(4, 2, 5, 1, 2, 7));
        Collections.sort(list);
        System.out.println("list = " + list);
        
        // B. 객체를 정렬할 경우 - 객체 내에서 Comparable인터페이스 구현
        // (사실 아래의 경우에는 ArrayList를 쓰고 sort를 하기보다 PriorityQueue를 쓰는게 더 효율적이다)
        ArrayList<Customer> customers = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            int no = (int)(Math.random() * 9999);
            String name = "이름없음" + no;
            customers.add(new Customer(no, name));
        }

        Collections.sort(customers);

        for (Customer one : customers) {
            one.print();
        }
        
    }
}

>> 결과

list = [1, 2, 2, 4, 5, 7]
1606=이름없음1606
2047=이름없음2047
4702=이름없음4702
6804=이름없음6804
9098=이름없음9098

 

|  자바 컬렉션들의 시간 복잡도

1. List

  add() remove() get() contains()
ArrayList O(1) or O(n) O(1) or O(n) O(1) O(n)
LinkedList O(1) O(1) O(n) O(n)

2. Set

  add() contains() next()
HashSet O(1) O(1) O(h/n)
LinkedHashSet O(1) O(1) O(1)
TreeSet O(log n) O(log n) O(log n)

3. Map

  add() containsKey() next()
HashMap O(1) O(1) O(h/n)
LinkedHashMap O(1) O(1) O(1)
TreeMap O(1) O(1) O(h/n)

4. Queue

  offer() peak() poll() size()
LinkedList O(1) O(1) O(1) O(1)
ArrayDequeue O(1) O(1) O(1) O(1)
PriorityQueue O(log n) O(1) O(log n) O(1)

 

 

 

 

[ 참고 및 출처 ]

부트 캠프 강의를 듣고 정리한 내용입니다.

자바 컬렉션의 시간 복잡도

https://hbase.tistory.com/185

https://velog.io/@sojukang/Map-%EB%82%B4%EB%A6%BC%EC%B0%A8%EC%88%9C%EC%9C%BC%EB%A1%9C-%EC%A0%95%EB%A0%AC-%EC%A0%80%EC%9E%A5

|  정렬이란

- 특정 값을 기준으로 데이터를 순서대로 배치하는 방법

- 기본 : 버블, 삽입, 선택

- 비교적 속도가 빠른 정렬 : 합병, 힙, 퀵, 트리

- 하이브리드 정렬 : 팀, 블록병합, 인트로

- 기타 : 기수, 계수(카운팅), 셸, 보고

 

|  정렬의 시간복잡도 요약

안정성이라는 것은, 어떤 데이터 { 1, 2, 3, 1, 1, 1 } 을 정렬한다고 할 때,

  같은 숫자 1에 대해서 { 1, 1, 1, 1 } 의 순서가 유지되도록 정렬되는 것을 '안정성이 있다'라고 한다.

- 아래의 보조 메모리는 추가적으로 드는 메모리를 이야기하는데,

  버블이나 삽입, 선택의 경우 swap시에 드는 변수 1개만 필요하기 때문에 보조메모리가 1개만 소요된다.

정렬 방법 시간 복잡도 보조 메모리 안정성
Ω(n) Θ(n) O(n)
버블 정렬 n n^2 n^2 1 o
삽입 정렬 n n^2 n^2 1 o
선택 정렬 n^2 n^2 n^2 1 x
합병 정렬 n log⁡n n log⁡n n log⁡n n o
정렬 n log⁡n n log⁡n n log⁡n 1 x
정렬 n log⁡n n log⁡n n^2 log⁡n x
트리 정렬 n log⁡n n log⁡n n^2 n x
기수 정렬 dn (*d:자릿수) dn dn n+k o
계수 정렬 n+k (*k:max) n+k n+k n+k o
셸 정렬 n log⁡n gap에 따라 다름 n^2 1 x

 

|  버블정렬 / 삽입 정렬 / 선택 정렬

// 버블 정렬
public static void bubbleSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        for (int j = 0; j < arr.length - i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1);
            }
        }
    }
}

// 삽입 정렬
public static void insertionSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        for (int j = i - 1; j >= 0; j--) {
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1);
            } else {
                break;
            }
        }
    }
}

// 선택 정렬
private static void selectionSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int min = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[min]) {
                min = j;
            }
        }
        swap(arr, i, min);
    }
}

 

|  합병정렬 / 힙 정렬 / 퀵 정렬 / 트리 정렬

1. 합병정렬

public static void mergeSort(int[] arr, int[] tmp, int left, int right) {
    if (left < right) {
        int mid = (left + right) / 2;
        mergeSort(arr, tmp, left, mid);
        mergeSort(arr, tmp, mid + 1, right);
        merge(arr, tmp, left, right, mid);
    }
}

public static void merge(int[] arr, int[] tmp, int left, int right, int mid) {
    int lCursor = left;
    int rCursor = mid + 1;
    int idx = left;

    while (lCursor <= mid || rCursor <= right){
        if (lCursor <= mid && rCursor <= right) {
            if (arr[lCursor] <= arr[rCursor]) {
                tmp[idx++] = arr[lCursor++];
            }else {
                tmp[idx++] = arr[rCursor++];
            }
        } else if (lCursor <= mid && rCursor > right) {
            tmp[idx++] = arr[lCursor++];
        } else {
            tmp[idx++] = arr[rCursor++];
        }
    }

    for (int i = left; i <= right; i++) {
        arr[i] = tmp[i];
    }
}

2. 힙 정렬

public static void heapSort(int[] arr) {
    // 가장 끝의 자식이 있는 부모노드를 잡아서 최대힙구조로 정렬
    for (int i = arr.length / 2 - 1; i >= 0; i--) {
        heapify(arr, i, arr.length);
    }

    // 가장 앞의 노드가 최대값임을 이용하여 나머지 정렬
    for (int i = arr.length - 1; i > 0; i--) {
        swap(arr, 0, i);
        heapify(arr, 0, i);
    }        
}

public static void heapify(int[] arr, int parentIdx, int size) {
    int leftIdx = parentIdx * 2 + 1;
    int rightIdx = parentIdx * 2 + 2;
    int maxIdx = parentIdx;

    if (leftIdx < size && arr[maxIdx] < arr[leftIdx]) {
        maxIdx = leftIdx;
    }

    if (rightIdx < size && arr[maxIdx] < arr[rightIdx]) {
        maxIdx = rightIdx;
    }

    if (maxIdx != parentIdx) {
        swap(arr, parentIdx, maxIdx);
        heapify(arr, maxIdx, size);
    }
}

public static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

3. 퀵 정렬

- pivot 값은 처음값이거나 중앙값이 될 수 있다. (상황에 맞게 선택하면 된다)

- 퀵 정렬은 pivot을 기준으로 좌우 정렬을 하고, pivot의 양 옆을 다시 분할하여 정렬하는 것을 반복한다.

public static void quickSort(int[] arr, int left, int right) {
    // 탈출문
    if (left >= right) {
        return;
    }

    // 피봇값 지정
    int pivot = partition(arr, left, right);

    // 피봇값의 좌우를 다시 퀵소트
    quickSort(arr, left, pivot - 1);
    quickSort(arr, pivot + 1, right);
}

public static int partition(int[] arr, int left, int right) {
    // 피봇값과 양 옆의 커서를 지정
    int pivot = arr[left];
    int lCursor = left;
    int rCursor = right;

    // 1. 양 끝의 커서가 서로 같기 전까지
    // 우측은 피봇값보다 더 작은 값을 찾고
    // 좌측은 피봇값보다 같거나 더 큰 값을 찾아 swap
    // 2. 양 끝의 커서가 서로 같아지면
    // 한쪽 커서와 피봇을 swap
    while (lCursor < rCursor) {
    	while (arr[rCursor] > pivot && lCursor < rCursor) {
            rCursor--;
        }
    
        while (arr[lCursor] <= pivot && lCursor < rCursor) {
            lCursor++;
        }

        swap(arr, lCursor, rCursor);
    }
    swap(arr, left, lCursor);

    return lCursor;
}

public static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

4. 트리 정렬

- 이진탐색트리를 만들어 정렬하는 방식으로, 알고리즘 복잡도는 NlogN이다.

- 이 부분은 비선형구조 > 이진탐색트리 포스팅에 적은 AVL, Red-Black을 확인해주세요.

 

|  기수 정렬 / 계수 정렬 / 셸 정렬

1. 기수 정렬

- 기수 : 자릿수를 의미한다.

- 기수정렬 : 일의 자리, 십의 자리, 백의 자리.. 순으로 각 자릿수에 해당되는 수를 큐에 담은 후 기존 배열에 넣는 방식

public static void radixSort(int[] arr) {
    // 각 자리에 큐를 담은 배열
    ArrayList<Queue<Integer>> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) { // 10진수 기준으로 자리 수 0 ~ 9
        list.add(new LinkedList<>());
    }

    // 최대 자릿수
    int maxLen = getMaxLen(arr);
    // 나누는 수
    int div = 1;
    // 배열에 넣어줄 인덱스
    int idx = 0;

    // 기수 정렬에 대한 반복문
    for (int i = 0; i < maxLen; i++) {
        // 해당 자릿수의 큐에 데이터를 추가
        for (int j = 0; j < arr.length; j++) {
            list.get((arr[j] / div) % 10).offer(arr[j]);
        }

        // 해당 자릿수의 큐를 가져와서, 기존 배열(arr)에 넣는다.
        for (int j = 0; j < 10; j++) {
            Queue<Integer> queue = list.get(j);

            while (!queue.isEmpty()) {
                arr[idx++] = queue.poll();
            }
        }

        // 그 다음 자릿수를 위한 준비작업
        idx = 0;
        div *= 10;
    }

}

// 데이터의 최대 자릿수 반환
public static int getMaxLen(int[] arr) {
    int maxLen = 0;
    for (int i = 0; i < arr.length; i++) {
        int len = (int)Math.log10(arr[i]); // 자릿수
        if (maxLen < len) {
            maxLen = len;
        }
    }
    return maxLen;
}

2. 계수 정렬

- 계수 : 관계가 있는 수, 상수를 의미한다.

- 계수정렬 : 상수 data 수열에서 최대값 + 1을 size로 배열에 생성해, 카운트한 후 다시 기존 배열에 넣는 방식

public static void countingSort(int[] arr) {
    // 최댓값의 + 1 만큼 배열을 잡아둔다
    int max = Arrays.stream(arr).max().getAsInt();
    int[] cntArr = new int[max + 1];

    // 숫자데이터에 해당되는 인덱스의 cnt를 하나 늘린다.
    for (int i = 0; i < arr.length; i++) {
        cntArr[arr[i]]++;
    }

    // cntArr을 한바퀴씩 돌면서 기존 배열(arr)에 해당 인덱스의 갯수만큼 삽입
    int idx = 0;
    for (int i = 0; i < cntArr.length; i++) {
        while (cntArr[i] > 0) {
            arr[idx++] = i;
            cntArr[i] -= 1;
        }
    }
}

//최댓값 하나만 너무 크면 비효율적 -> HashMap을 통해 보완할 수 있다
public static void countingSort2(int[] arr) {
    // key : data, value : 갯수
    HashMap<Integer, Integer> map = new HashMap<>();
    for (int item : arr) {
        map.put(item, map.getOrDefault(item, 0) + 1);
    }

    // key를 배열에 담아서 정렬한 후, 기존 배열(arr)에 해당인덱스의 갯수만큼 다시 삽입한다.
    ArrayList<Integer> keyList = new ArrayList<>(map.keySet());
    Collections.sort(keyList);
    int idx = 0;
    for (int key : keyList) {
        int cnt = map.get(key);
        while (cnt > 0) {
            arr[idx++] = key;
            cnt--;
        }
    }
}

3. 셸 정렬

- 삽입 정렬을 보완한 형태로 

- 삽입 정렬은 idx 1부터 arr.length-1까지 처음부터 좌측의 데이터를 확인했다면

- 셸 정렬은 간격을 두고 간격의 거리만큼 떨어진 데이터를 확인하는 것을 반복한다.

- 이렇게 하게 되면 기존의 삽입 정렬 보다는 교환 횟수가 감소할 수 있다.

public static void shellSort(int[] arr) {
    // 초기 gap을 설정
    int gap = arr.length / 2;

    // 더 이상 간격이 없을 때까지 간격을 /2한다.
    for (int g = gap; g > 0; g /= 2) {
        // 초기 간격부터 간격의 길이만큼 증가하면서
        for (int i = g; i < arr.length; i++) {
            // 지정된 위치의 좌측 간격들의 데이터를 비교 & 교환한다.
            int tmp = arr[i]; // 짚은 데이터를 tmp에 넣고
            int j = 0; // 짚은 데이터의 좌측 데이터들을 확인
            for (j = i - g; j >= 0; j -= g) {
                // 큰 값이 나오면 좌측 데이터들을 하나씩 당긴다
                if (arr[j] > arr[j + g]) {
                    arr[j + g] = arr[j];
                } else {
                    break;
                }
            }
            arr[j + g] = tmp;
        }
    }
}

 

 

[ 출처 ]

- 부트캠프 강의를 듣고 정리한 내용입니다.

|  데이터베이스의 순위

- 출처 : https://db-engines.com/en/ranking

- 2022년을 기준으로 데이터베이스의 순위는 아래와 같다

* 아래 [바로가기]를 선택 시, 해당 DBMS 사용 메뉴얼로 이동

- 예전에 오라클을 설치하는 것을 포스팅한 적이 있었는데 이번에는 MariaDB를 설치하는 법을 작성해보려한다.

1 Oracle RDMBS 오라클사 바로가기
2 MySQL RDMBS 오라클사 바로가기
3 Microsoft SQL Server RDMBS Microsoft 바로가기
4 PostgreSQL RDMBS PostgreSQL단체 바로가기
5 MongoDB NoSQL계열 MongoDB, Inc 바로가기

 

|  MariaDB 설치하기

1. Windows 환경

(1) 다운로드 사이트로 이동 [바로가기]

- 컴퓨터 OS환경에 맞춰서 설치하면 된다. (Package Type은 Zip으로 하는 것이 차후 세부설정을 하기 편하다)

(2) 다운되면 압축을 푼다.

(3) 관리자 권한 CMD에서 압축을 푼 경로로 이동 후 설치파일을 실행한다.

** 관리자 권한으로 열어주는 이유 : 보안 이슈로 서비스 등록을 처음할 때는 관리자 권한이 있어야만 가능

** 사용자용 CMD 관련 팁 : 파일탐색기 경로창에 "cmd" 입력 후 엔터를 치면 사용자용 cmd가 알아서 뜬다.

cd /* 압축 푼 폴더 경로 */
cd /bin

** 설치파일을 실행하기 전에, 명령어 옵션에 대한 정보를 --help로 확인하면 좋다.

mariadb-install-db.exe --help  // 설치파일에 관한 정보 확인

mysql_install_db.exe  Ver 1.00 for Windows
Copyright (C) 2010-2011 Monty Program Ab & Vladislav Vaintroub
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL v2 license
Usage: mysql_install_db.exe [OPTIONS]
OPTIONS:
  -?, --help          Display this help message and exit.
  -d, --datadir=name  Data directory of the new database
  -S, --service=name  Name of the Windows service
  -p, --password=name Root password
  -P, --port=#        mysql port
  -W, --socket=name   named pipe name (if missing, it will be set the same as
                      service)
  -D, --default-user  Create default user
  -R, --allow-remote-root-access
                      Allows remote access from network for user root
  -N, --skip-networking
                      Do not use TCP connections, use pipe instead
  -i, --innodb-page-size=#
                      Page size for innodb
  -s, --silent        Print less information
  -o, --verbose-bootstrap
                      Include mysqld bootstrap output
  -l, --large-pages   Use large pages
  -c, --config=name   my.ini config template file

> 이 중에서 서비스명, Root password를 지정하는 옵션을 뽑아 명령어를 쓴다.

mariadb-install-db.exe -S 서비스명 -p 비밀번호  // 오류가 뜬다면 관리자권한CMD인지 확인하자

- [작업관리자] - [서비스]로 들어가면 서비스가 잘 등록된 걸 볼 수 있다.

(5) 실행하기

A. 서비스 직접 실행

sc start MariaDB

B. mysql.exe로 실행

- MariaDB 압축파일을 풀었던 경로의 bin폴더로 가서 mysql.exe 명령어 option을 확인한다.

mysql.exe --help

>> 엄청나게 옵션이 많은데 다른 건 필요없고 아래 두가지만 확인하면 된다.

 -u, --user=name     User for login if not current user.
 -p, --password[=name]
                      Password to use when connecting to server. If password is
                      not given it's asked from the tty.

- 여기서 user는 root로 지정하고, pwd는 처음 설치할 때 지정한 root password를 넣어준다

(root는 서비스의 최상위 권한자이다.)

mysql.exe -u root -p 
지정한RootPassword 입력

- 실행이 잘 되었는지 아래 코드를 통해 확인해본다.

select version(); - 버전명 확인

show databases; - 현재 계정에서 확인할 수 있는 등록된 DB들

use mysql; - 사용

show tables; - 테이블 목록 확인

select Host, User, Password from user; - 호스트(로컬or외부), 계정, 비밀번호 확인

 

2. MacOS 환경

(1) 패키지 매니저 "홈브루"를 설치한다.

- 맥의 터미널은 iterm2를 다운받아 터미널로 사용할 수 있다.(UI면에서 더 편리하다)

- 홈브루 설치 메뉴얼 : https://brew.sh/index_ko

: 아래 명령어를 작성해서 홈브루를 설치한다

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

(2) 홈브루를 통해 MariaDB 버전을 확인한다.

brew search mariadb   //MariaDB 각 버전 검색
brew info mariadb     //default version인 mariadb에 대한 정보 확인

(3) 홈브루를 통해 선택한 버전의 MariaDB를 설치한다

brew install mariadb

- 설치 후에, 다시 아래 명령어를 입력하면 설치된 버전이 체크된 걸 볼 수 있다

brew search mariadb

- 설치 후에는 설치된 경로를 알려주는데, 해당 경로를 꼭 따로 입력해주는 것이 좋다.

(4) 터미널에서 (3)에서 확인한 경로로 이동

- 현재 경로를 확인하고 설치 경로로 이동한다.

pwd   // 현재 경로확인
cd mariadb경로

- bin 폴더에서 ls를 통해 파일 목록을 확인하면,

  mariadb_secure_installation(주황색), mysql_secure_installation(보라색) 두가지가 있는걸 볼 수 있는데, 

  --> 주황색 표시된 mariadb_secure_installation이 실질적인 설치 파일이고,

  --> 보라색 표시된 mysql_secure_installation은 그걸 참조한다.

  *** 우리는 이 중에서, mariadb_secure_installation를 설치하면 된다.

(5) 관리자 권한으로 설치파일 실행 

// su : 관리자 권한 실행
// ** mac이나 linux는 꼭 앞에 ./ 현재 경로 입력해야 실행된다
su ./mariadb_secure_installation

- Root password 및 기타 설정을 설정한다

- 모두 설치한 후 잘 설치되었는지 확인하려면 아래를 입력하면 된다.

brew services info mariadb

(6) 서비스 실행하기

brew services start mariadb
//brew services restart mariadb 
//bres services stop mariadb

 

3. Linux 환경 

(1) 패키지 매니저를 설치한다.

- 우분투의 경우 apt, CentOS의 경우 yum을 통해 설치한다.

(2) MariaDB 버전 확인 후 설치파일 다운로드

- 패키지 매니저를 통해 MariaDB 버전을 확인하거나

apt search mariadb-server

- MariaDB 사이트에서 버전 확인 후 가이드에 따라 설치파일 다운로드[바로가기]

(4) MariaDB 설치파일 실행

sudo -i //관리자 권한 실행
find / -name mariadb-secure*  //파일 경로 확인
apt mariadb-secure-installation //설치파일 실행

(5) 서비스 실행하기

service mariadb start

 

원격으로 외부 DB서버에 접속하는 방법(윈도우 기준)

- 들어가기 전에

- 일반적으로 Root는 원격으로 접속할 수 없도록 되어 있다.
- Shell을 통해 원격접속을 할 때에는
   A. SSH를 통해서 DB컴퓨터에 접속 후 DBMS에 접근하거나
   B. DB컴퓨터에서 외부IP의 포트 및 계정 권한을 허용한 경우 접근할 수 있다. 

- Shell이 아닌 IDE(IntelliJ, Eclipse등)에서 접속을 할 경우에도,
  마찬가지로 DB컴퓨터에서 나의 접근을 허용해주어야만 접근이 가능하다.
- 원격 접속하는 걸 연습할 때는 xShell을 쓰면 유용하다 (xShell 다운 바로가기)
  현장에서는 PuTTY를 더 자주 쓴다.

 

사용자를 포함해서 개발자도 웹 서버를 통해 DB와 소통을 한다.

다만, 때에 따라 개발자가 DB서버에 직접적으로 접근을 해야하는 경우도 있는데

보안상 DB 서버는 따로 두는 경우가 많아서 이런 경우 DB 서버에 원격으로 접속하는 것이 필요하다.

원격으로 서버에 접속하기 위해서는 기본적으로 아래와 같은 정보들이 필요하다.

[ 원격으로 서버에 접속하기 위한 정보 ]

구분 설명 예시
주소(IP)  특정 시스템의 주소 - 내컴퓨터(로컬) : 127.0.01, localhost
- 외부 : 168.xxx.xx.x 
포트(PORT)  그 시스템 내 프로그램 위치 - 3306(MariaDB의 디폴트 포트)
- 22(웹)
...
계정  서비스 계정  
비밀번호 그 계정의 비밀번호  
인스턴스     

 

A. SSH를 통해 내 컴퓨터(윈도우)에서 DB컴퓨터(Linux)에 접속하기

(1) xShell을 설치하고 실행한다.

(2) IP주소를 확인하여 SSH를 통해 접속하기 (접근 시 비밀번호 작성)

ssh satcop@접속할ip주소

(3) 해당 ip 내에서 DBMS 접속하기

mysql -u root -p

 

B. DB컴퓨터(Linux)가 내 컴퓨터(윈도우) IP의 포트 및 계정 권한 허용

[ DB컴퓨터(Linux)에서 아래와 같이 작업이 필요하다]
1. DBMS 설정(my.cnf)에서 외부 IP도 DBMS 포트에 접속할 수 있게 설정하기
2. DBMS 계정을 만들어 외부IP와 연결하기

- 윈도우 cmd에서 아래와 같은 코드를 작성하여 바로 접근을 하려 하면 "can't connect to server on 'ip주소'"가 나타난다.

mysql -h 외부ip주소 -u root -p

- 이유는 DB를 담고 있는 PC에서 MariaDB 포트를 열어두지 않았기 때문이다.

- DB를 담고 있는 PC(linux)에서 아래의 명령어를 통해 현재 활성화된 포트를 확인해보면

netstat -anpt

- 아래와 같이 MariaDB 포트가 로컬컴퓨터에서만 열려 있는 걸 볼 수 있다. 

* 로컬 컴퓨터 주소 : 127.0.0.1

* MariaDB 디폴트 포트 : 3306

Proto  (생략)  Local Address    (생략)
tcp            127.0.0.1:3306

- DB를 담고 있는 PC(linux)의 MariaDB 설정파일(my.cnf)에서 외부ip 접근을 허가한다.

sudo -i                 //관리자권한 실행
find / -name my.cnf     //my.cnf (설정파일) 경로 확인
cd /etc/mysql           //해당 경로로 이동
vi my.cnf               //my.cnf 실행

[mysqld]                //설정파일에서
bind-address=0.0.0.0    //모든 외부ip접근 허가(또는 특정짓기)

service mariadb restart //MariaDB 재실행

- 허가를 하면 아래와 같이 모든 ip에서 3306포트가 열린 걸 볼 수 있다.

Proto  (생략)  Local Address    (생략)
tcp            0.0.0.0:3306

- 이렇게만 하면 접속이 가능해질까? 그렇지 않다.

  아래를 보면 알 수 있듯이 root 계정은 localhost에서만 사용가능하기 때문에 새롭게 계정을 만들어 주어야 한다.

use mysql
select Host, User from user;
+-----------------+-------------+
| Host            | User        |
+-----------------+-------------+
| 127.0.0.1       | root        |
| ::1             | root        |
| desktop-ivvs8i6 | root        |
| localhost       | mariadb.sys |
| localhost       | root        |
+-----------------+-------------+

- 새로운 계정을 만들어 주면서, 모든 ip에서 접속가능하게 설정하기

create user 'root'@'%' indentified by 비밀번호; // '%' : 어떤 호스트에서든 접속 가능
grant all privileges on root.* to 'root'@'%' indentified by 비밀번호;  // 권한설정
flush privileges;

 

|  사용된 CLI 명령어 정리

windows CLI 명령어

cd 경로 이동 cd ~ : desktop 폴더로 이동
cd .. : 상위 경로
cd .  : 현재 경로
[tab] : 일부 작성 후 [tab]을 누르면 유사파일명 자동입력
dir 현재 경로의 폴더(디렉토리)와 파일 목록을 보여줌 /w : 목록이 3개씩 표시
cls (=clear) 화면을 지워준다.  
--help 명령어 + --help를 쓰면
명령어 실행 전에 설명을 띄워준다
 
sc sc start 서비스명 : 등록된 서비스 시작
sc restart 서비스명  : 등록된 서비스 다시시작
sc stop 서비스명 : 등록된 서비스 멈춤
관리자권한이 있어야만 가능
exit CLI 종료  
ipconfig 현재 ip 주소 반환  

macOS CLI 명령어

cd 경로 이동  
pwd 현재 경로를 알려준다  
ls 현재 경로의 폴더(디렉토리)와 파일 목록을 보여줌 ls - al : 파일 목록을 상세하게 확인
su (=sudo) 관리자 권한으로 파일 실행  
find / -name 특정 파일의 경로를 찾아준다  
quit CLI 종료  

Linux CLI 명령어

pwd 현재 경로를 알려준다  
ls 현재 경로의 폴더(디렉토리)와 파일 목록을 보여줌 ls - al : 파일 목록을 상세하게 확인
find 특정 파일의 경로를 찾아준다  
sudo 관리자 권한으로 파일 실행 sudo i
ifconfig 현재 ip 주소 반환  
find / -name 특정 파일의 경로를 찾아준다  
service 서비스를 start/restart/stop ex. service mariadb start

 

 

[ 참고 및 출처 ]

부트캠프 강의를 듣고 정리한 내용입니다.

우분투와 CenOs https://forteleaf.tistory.com/entry/CentOS-%EB%8C%80-Ubuntu-%EC%84%9C%EB%B2%84%EC%97%90-%EB%8D%94-%EC%A2%8B%EC%9D%80-%EA%B2%83

openSSH https://velog.io/@hyeseong-dev/%EB%A6%AC%EB%88%85%EC%8A%A4-ssh%EB%9E%80

|  제네릭이란?

[사전] Generic = 일반적이다
[정의] 하나의 코드로 여러 타입을 동시에 처리하는 기술

1.  타입 변수 표기법

- 제네릭에 지정하는 타입 변수 이름은 지정하는 사람의 마음이지만,

  적어도 그 타입 이름을 사용하는 클래스 또는 인터페이스 내에서는 통일성있게 사용하게 한다.

- 일반적으로 변수명과의 구분을 위해 한 개의 대문자로 표시하는 것이 관례이다.

- 타입 매개 변수는 기초 자료형으로 객체화될 수 없다.

 

T Type
E Element(요소)
N Number
K Key
V Value
S,U,V.....  

 

2. 제네릭 클래스

- 최상위 클래스 Object를 사용하면 어떤 타입의 인스턴스건 참조할 수 있다. (업캐스팅, 다형성)

- 이러한 원리를 이용해서 클래스를 작성할때 데이터 타입을 Object로 하면 여러 타입의 데이터를 담을 수 있게 된다.

public class Box {
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

}

- 다만, 이럴 경우, 아래와 같이 객체 안의 데이터를 가져올 때 형변환이 불가피하게 된다.

import LibraryPractice.MyClass.Box;

public class GenericTest {
    public static void main(String[] args) {
        Box box = new Box();
        box.setData(123);
        int x = (Integer)box.getData(); //cast(형변환)필요
    }
}

- 이럴 때 제네릭을 사용하여 미리 타입을 지정한다면 사용시의 형변환의 번거러움을 줄일 수 있게 된다.

public class Box<T> {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

}
import LibraryPractice.MyClass.Box;

public class GenericTest {
    public static void main(String[] args) {
        Box<Integer> box = new Box<>();
        box.setData(123);
        int x2 = box.getData(); // 형변환 필요 없음
    }
}

- 만약에 여러 개의 맴버변수에 서로다른 제네릭을 지정해야하는 경우(ex. key와 value가 타입이 다른 경우), 아래와 같이 작성할 수 있다.

public class Box3<K, V> {
    private K key;
    private V value;

    public void setData(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey(V key) {
        return this.key;
    }

    public V getValue(K key) {
        return this.value;
    }

}

 

3. 제네릭 메소드

- 제네릭 메소드의 경우 아래와 같이 반환타입 앞에 <E> 와 같은 형식으로 작성을 해준다.

public class Basket<T> {

    T data;

    public Basket(T data){
        this.data = data;
    }

    // 외부 배열 print
    public <E> void print(E[] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

}

- 만약에 타입 변수를 특정 타입(예를 들어 String)으로 제한하고 싶은 경우, 아래와 같이 사용할 수 있다.

public <E extends String> 반환타입 method(E item){
	/* 생략 */
}

 

[ 제네릭 메소드로 만든 코드 ]

import java.util.ArrayList;
import java.util.Arrays;

public class Basket2<T> {
    private ArrayList<T> basket;

    public Basket2(T[] arr) {
        this.basket = new ArrayList<T>(Arrays.asList(arr));
    }

    public <E extends String> void printWithOwner(E str) { // E를 String으로 제한
        if (str.length() == 0) {
            System.out.println("please type Owner Name");
            return;
        }

        StringBuffer sb = new StringBuffer();
        sb.append(str + " : ");
        for (int i = 0; i < basket.size(); i++) {
            if (i != basket.size() - 1) {
                sb.append(basket.get(i) + ", ");
            }else{
                sb.append(basket.get(i));
            }
        }
        System.out.println(sb);
    }

}
import LibraryPractice.MyClass.Basket2;

public class GenericTest2 {
    public static void main(String[] args) {

        String owner = "sir.Tim Berners-Lee";
        String[] fruit = {"apple", "orange", "dragon fruit"};

        Basket2<String> basket = new Basket2<>(fruit);
        basket.printWithOwner(owner);

    }
}

>> 결과

sir.Tim Berners-Lee : apple, orange, dragon fruit

+ Recent posts