본문 바로가기
비전공자의 코딩 일지/학원 수업 정리

코딩 학원 18일차 (Java Collection)

by Hoder2 2022. 6. 30.

강사님이 매번 말씀 하시는 하나의 프로그래밍 언어를 잘 한다라고 하면 반복문, 조건문, 배열, 그 언어만의 특징을 잘 쓸 수 있어야 한다고 하셨는데 다른건 빡세게 배운 것 같은데 유독 배열만 부실하게 배운 느낌이 있다.

우리가 배운 배열은 1차원, 2차원 배열 그리고 그 배열에 접근하는 방식들이다.

근데 이게 뭐냔다.

 

Java 배열의 단점

1. 배열은 의미를 알아보기가 힘들기에 유지보수가 힘들다. 그 어딜봐도 저게 수학 점수라는 말이 없기 때문이다.

2. 한번 배열의 크기를 정하고 난 뒤에 변경할 수 없기 때문에 내가 받아놓은 데이터의 양을 정확하게 알기 어려워 배열에 활용하기가 어렵다.

3. 그리고 점수만 저렇게 덜렁 있으면 뭐가 누구 점수인지 알 수가 없는데 int와 String을 섞어 쓰지 못한다.

 

결론은 배열을 왜 쓰냐는 말이다.

그래서 collection으로 간다.

 

-collection

 

collecton 중에는 List 계열, Set 계열, Map 계열이 있는데 특징은 다음과 같다.

 

List 계열 : 가변사이즈 배열
ArrayList, Vector, ...
Set 계열 : 가변사이즈, 중복데이터 x, 순서랜덤
HashSet, TreeSet, ...
Map 계열 [dict(사전), NSDictionary] : 가변사이즈, 순서개념x, 키 - 값 형태
HashMap, HashTable, ...

 

배열 같은 경우 만들 때 사이즈를 지정해줘야 하지만

collection은 이런식으로 객체 생성 시에 사이즈 몰라도 되며

이렇게 값을 나중에 추가할 수도 있다. 심지어 글자도 섞어서 가능하다.

값을 불러오는 방식은 배열과 비슷하며 길이는 length가 아니고 size로 부른다.

자동완성 시에 저렇게 <E>를 주는데 이걸 generic이라고 부르고 자료형만 쓸 수 있게 강제하는 기능이다.

이렇게 int를 넣고 마저 적어보면 이 collection의 기본 속성, 객체만 넣을 수 있다. 

이런식으로 객체(자료형)만 넣을 수 있다. 그런데 기본형과 객체형 사이의 변화는 알아서 해주기 때문에 굳이 저렇게 까지 할 필요는 없고 al2.add(20) 이렇게 넣어도 된다. 다만 이게 int가 아니고 Integer로 자동형변환된 20인 것이다.

그리고 값에 접근할 때는 get을 쓴다. 또한 List도 forech 사용이 가능하다.

그리고 add를 이용하면 알아서 맨 뒤로 들어가게 되는데

이렇게 위치 값을 넣어주면 알아서 그 자리에 100을 넣고 나머지는 뒤로 한칸씩 밀어준다.

이렇게 1번 위치의 값을 지우는 것도 가능하다.

이렇게 set으로 0번의 값을 999로 바꾸는 것도 가능하다.

Comparator를 이용해 정렬 또한 가능한데 객체가 아닌 인터페이스이기 때문에  객체로 생성해주면 알아서 형식을 맞춰준다.(빨간줄에 마우스 갖다대야 함.)

그리고 이렇게 오름차순 내림차순으로 정렬이 가능하다.

 

List 계열에 Vetor도 있으나 강사님이 Vetor를 안 쓰는 이유는 기능적으로는 똑같지만 싱크로나이즈드 기능을 포함하고 있기 때문에 멀티 쓰레드를 이용할 때 안전성을 추구한다면 쓰고 아니라면 그냥 ArrayList를 쓴다고 하셨다.

 

이제 어떤 학급의 학생들의 성적을 나열해보라 하셨다.

 

이런식으로 생성한 객체를 ArrayList에 집어 넣을 수 있고 값을 접근할 때는 변수명.get(index).객체의 메소드 이런식이다.

(Student 객체의 멤버변수에 private를 걸고 getter와 setter를 통해 값을 만질 수 있게 해놨으니 어찌보면 당연하다.)

이렇게 다양한 문제들을 풀어봤다.

이름 가나다순 정렬은 String을 가져와서 그 가져온 글자와 비교를 해주게끔 만든다.

오름차순 내림차순 응용법.

 

다음은 우리가 어제 만든 실시간 날씨 데이터를 불러와서 

이 형식으로 출력되게 만들라 하셨다.

1. 파일 불러오기 및 파일에 있는 데이터를 만질 수 있게끔 Stream을 꽂아준다.

2. 파일을 한줄씩 읽고 그 문장을 저장해줄 String 변수를 하나 만들고 한줄 한줄 객체로 만들어줄 반복문을 만든다.

3. 객체에 들어온 데이터 값을 원하는 형태로 정리해주는 메소드를 만들고 출력 형식도 만들어준다.

4. 메인 클래스에서 객체의 출력 기능을 부른다.

 

말은 어렵게 보이지만 직접 쓰는건 더 어렵다. 보통 그렇더라.

 

이번엔 지하철 자료 받아왔던 것을 불러와서 이용객(탑승객+하차객)이 가장 많은 정거장의 모든 정보가 출력되게 해보라 하셨다.

날짜 : 2015년 01월 01일
호선 정보 : 1호선
정차역 : 서울역
탑승객 : 
하차객 :
--------------------------------

이런 틀로 나오게 말이다.

위에서 날씨로 뭐 만든 거랑 크게 다른건 없다. 다만 위에선 객체로 만들고 객체 내 메소드에서 배열로 만든 것에서 그쳤다면 여기서는 객체로 만든 데이터를 컬렉션으로 만들어 놨다는 것이다. 그리고 그 컬렉션으로 이것저것 해본 정도.

그리고 승차객 총합과 하차객 총합 구할 때 이상하게 똑같은 숫자로 값이 나왔는데

알고보니 int 저장용량의 최대치를 넘겨버려서 그 숫자에서 막힌 거였고 long으로 바꿔주니 정상 출력이 가능했다.

그리고 이 소스를 추가해주면

이런식으로 값 안에 보기 쉽게 콤마를 넣어줄 수도 있다. (7년치라 그런지 173억이라는 숫자가 나왔다.)

 

그리고 여담으로 강사님이 데이터를 파실할 때 콤마가 있을 것 같으면 csv를 함부로 쓰면 안 된다고 하셨다.

고속터미널, 강남역(강남, 강남역), 신논현역 이런식으로 괄호안에 콤마가 들어 있으면 참사가 벌어진단다.

 

-Set

 

이제 Set계열로 넘어가자.

 

HashSet 같은 경우 중복된 값을 넣으면 알아서 없애주고 출력되는 값이 랜덤으로 나오며 ArrayList와 다르게 get이 없다.

위 처럼 생성자에 컬렉션 명을 넣고 컬렉션들간의 변환 또한 가능하다.

위는 HashSet을 ArrayList로 변환 한 것이고 주된 목적은 get을 쓰기 위함이다.

 

로또 기계를 만들어 보라 하셔서

이런식으로 만들었는데 예전에 개고생하던 것에 비해 무척이나 쉽게 만들어져서 코딩은 아는게 많을수록 쉽고 효율적으로 소스를 짤 수 있구나라는 생각이 들었다. 그리고 강사님이 이 Set 계열은 생각보다도 활용도가 더 떨어지는 것이라 했다.

 

학생하나를 만들어 보라 하셨다. 그리고 값이 중복 되는 다른 학생을 하나 더 만들라 하셨다.

그렇다면 지금 저 Set의 사이즈는?

기적적으로 모든 점수가 같고 이름 까지 같은 학생 2명이기 때문에 2가 나온다.

근데 이것도 2가 나온다.

 

값이 같냐는 아무런 상관이 없고 정말로 다른 객체를 집어 넣었느냐가 중요하단 것이다. 결론은 이 중복 제거라는 개념이 그렇게 활용도가 크지 않다는 것이다.


그럼 이걸 어디에 써먹는가??

 

기본형급 저장된 List가 있다고 하자.
ArrayList이고 Integer 혹은 String인데 값에 중복 되는 값이 있을 때

이렇게 담궜다 빼서 중복된 값을 빼는 정도로만 사용을 한단다. 다만 순서는 개판이 난다. 그래서 정렬은 ArrayList를 쓴다.

 

-map

 

파이썬에서는 dict(사전)라고 불린단다. 배열, 컬렉션 같은 경우 순서를 찍으면 그 위치에 있는 값이 튀어나오지만 (Set은 랜덤) map 같은 경우 사전에서 누가 번호로 값을 찾겠냐고 하셨다.

이렇게 String 키 값을 넣으면 Integer 결과 값을 찾아주는 컬렉션이다. (키보드 넣을 시 10000이 나오는)

근데 이렇게 하면 값을 덮어버리는지 아래있는 32000 하나만 나온다.

이 소스 정확히 이해가 안 간다. 아마 졸았나 보다.

 

학생 검색기능을 만들어보자 하셨다. 콘솔창에 번호를 치면 정보가 나오게

이렇게 ArrayList를 활용하지 않을까 하셨다. 그러니까 일반적인 경우엔 이걸 쓴다 하셨다.

 

그럼 이제 이름을 입력하면 그 사람의 정보가 나오도록 해보라 하셨다. 이렇게 숫자로 값을 찾는게 아니라면 Map을 쓰라고 하셨다. 정렬도 안 되고 통계도 안 되는데 딱 검색 용도로 사용하기 좋다고 하셨다.

이런식으로 String이 키 값이고 나오는 값이 Student 객체로 나오게 끔 설정해주면 된다.

아무튼 주력은 List고 이런 예외적인 상황일 때 Map을 쓰면 된다고 하셨다.

 

그럼 이제 지하철 2차전으로 가자 하셨다.

각 호선별 전체 탑승인원의 합을 구해보자 하셨다.

아까 subway 객체틀을 그대로 이용해서 만든 것이다. 근데 중간에 객체명이랑 변수명이 강사님이랑 전부 달라서 급하게 따라쓰고 다시 다 고쳐 쓰다가 무슨 내용인지 다 놓쳐버렸다.

 

기본적인 형식은 아까 처럼 파일 불러오고 반복문으로 객체 만들어주면서 map에 넣어주는건 변함 없어 보인다.

문제는 저 containskey라는 친구인데 짐작하건데 원래 있던 키 값이면 map에 추가하고 원래 있던 map에 값도 더하고 그게 아니라 처음 보는 키 값이면 키 값이랑 sum 값 map에 추가해라 느낌인 것 같다. 내일 수강생들 한테 다시 물어봐야겠다.