18일차(3)/java(22) : Util Class (ArrayList, HashMap)
Step12_UtilClass 프로젝트 생성
<MainClass01>
package test.main;
import java.util.ArrayList;
/*
* java에서 배열은 크기를 조절할 수 없는 고정 배열이다.
* 따라서 동적으로 item을 추가하고 삭제하고 하는 작업을 하려면 일반배열은 사용할 수 없다.
* 그래서 해당 작업을 하려면 ArrayList 객체를 사용하면 된다.
*/
public class MainClass01 {
public static void main(String[] args) {
//String type을 저장할 수 있는 ArrayList 객체생성
ArrayList<String> names=new ArrayList<>();
//"바나나", "딸기", "복숭아" 3개의 String type을 저장해 보세요.
names.add("바나나");
names.add("딸기");
names.add("복숭아");
//0번방의 아이템을 불러와서 item이라는 변수에 담아보세요.
String item=names.get(0);
//1번방의 아이템을 삭제하려면?
names.remove(1);
//0번방에 "아이스크림"을 넣고 싶으면?
names.add(0, "아이스크림");
//저장된 아이템의 갯수(size)를 size라는 지역변수에 담아 보세요.
int size=names.size();
//저장된 모든 아이템 전체 삭제
names.clear();
}
}
- ArrayList 배열식 사용방법
- ArrayList는 java.Util이라는 패키지 안에 들어있다.
- ArrayList 배열인데, 이 배열에 어떤 타입을 저장할 것인지 정하는 것이다.
ArrayList<데이터타입> 배열을 담을 변수명
- javascript 의 let names=[ ]; 와 비슷하다.
- 점을 찍어보면 여러 메소드들이 있다. 이 중 아이템을 추가할 때는 add 사용.(javascript의 push)
- ArrayList에 String type을 담을 예정이라서 <>을 String으로 넣어줌
- 위의 add는 String 값을 받는 메소드이다.
- 밑의 add는 인덱스번호를 넣으면 원하는 인덱스에 넣을 수 있는 메소드이다.
→ add 메소드가 다중정의되어 있다(overloading) 고 한다.
names.get(0);
- 위와 같은 형태로 인덱스번호를 받아 값을 가져온다. javascript array 였다면 names[0] 이라고 썼을 것.
- remove도 다중정의되어 있다.
삭제할 아이템의 값을 알려주는가(int) / 참조값을 알려주는가(object) 의 차이!
참고) 메소드의 이름들은 대체로 비슷한데, 보통 직관적으로 알 수 있게 되어있다.
.addXXX : 새로운 것을 더하는 메소드
.setXXX : 구성을 갖추고 세팅하는 메소드
.getXXX : 아이템을 참조하고 가져오는 메소드
names = [바나나, 딸기, 복숭아]
- 디버그모드를 보면 names.add를 통해 배열이 생성된 것을 볼 수 있다.
- 1번을 삭제하면 뒤에 있는 2번 인덱스가 앞으로 당겨지고,
0번 방에 값을 새로 넣으면 인덱스가 다 하나씩 뒤로 밀린다.
- 상속 클래스 타입으로 4개, 인터페이스 타입으로 6개 : 총 10가지 타입으로 받을 수 있다.
- ArrayList, List 타입을 가장 많이 쓴다.
- 자주 사용되는 add/remove/get/clear/size 는 List 인터페이스에 정의되어 있다.
List 인터페이스를 구현한 객체들은 모두 저 메소드(빨간 박스)가 동일하다.
ArrayList<String> names=new ArrayList<>();
List<String> names=new ArrayList<>();
- 위를 아래와 같이 바꿔도 오류가 없다.
<MainClass02>
package test.main;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class MainClass02 {
public static void main(String[] args) {
//ArrayList 객체를 생성해서 List 인터페이스 type 지역변수에 참조값 담기
List<String> names=new ArrayList<>();
names.add("바나나");
names.add("딸기");
names.add("복숭아");
names.add("사과");
names.add("오렌지");
//반복문 돌면서 친구 이름을 순서대로 콘솔창에 출력해보기
for(int i=0; i<names.size(); i++) {
String tmp=names.get(i);
System.out.println(tmp);
}
System.out.println("----확장 for문을 사용하면 ----");
for(String tmp:names) {
System.out.println(tmp);
}
System.out.println("----forEach() 메소드 활용1 ----");
Consumer<String> con=new Consumer<>() {
@Override
public void accept(String t) {
System.out.println(t);
}
};
names.forEach(con);
System.out.println("----forEach() 메소드 활용2 ----");
Consumer<String> con2=(t)->{
System.out.println(t);
};
names.forEach(con2);
System.out.println("----forEach() 메소드 활용3 ----");
names.forEach((t)->{
System.out.println(t);
});
}
}
- ArrayList에서 for 문 작성하기
1) 일반 for문
for(int i=0; i<names.size(); i++) {
String tmp=names.get(i);
System.out.println(tmp);
}
2) 확장 for문
for(String tmp:names) {
System.out.println(tmp);
}
- 배열을 담을 임시변수를 콜론 : 좌측에 써주면 알아서 for문이 돌면서 tmp배열을 하나씩 출력해준다.
3) forEach 함수 사용
- javascript: forEach에 함수를 넣어주면 배열의 아이템만큼 호출되면서 item에 순서대로 값이 전달된다.
- java: forEach에 Consumer type 참조값을 넣어준다.(함수가 단독으로 존재할 수 없으므로)
- Consumer type의 참조값을 넣어주면 인터페이스 안에 있는 메소드(1개짜리 메소드)가
배열의 아이템만큼 알아서 호출되면서 배열의 아이템을 하나씩 내보내준다.
Consumer<String> con=new Consumer<>() {
@Override
public void accept(String t) {
System.out.println(t);
}
};
names.forEach(con);
- Consumer 인터페이스를 구현하는 익명 클래스 사용
Consumer<String> con=new Consumer<>() { }; ← class ? implements Consumer
- Consumer가 하나씩 호출하면서 accept라는 메소드에 값이 순서대로 하나씩 전달된다.
4) forEach 함수 활용 2
Consumer<String> con2=(t)->{
System.out.println(t);
};
names.forEach(con2);
- override, 데이터 타입을 생략하고 참조값을 con2 변수에 넣어준다.
5) forEach 함수 활용 3
names.forEach((t)->{
System.out.println(t);
});
- 배열명.forEach(()->{}); 형태로 만들어 줄 수도 있다.(메소드가 하나만 있는 경우)
- 굳이 변수를 만들 필요가 없으므로 con2라는 변수마저도 생략한 것!
<MainClass03>
package test.main;
import java.util.ArrayList;
import java.util.List;
public class MainClass03 {
public static void main(String[] args) {
//정수를 저장할 수 있는 ArrayList 객체를 생성해서 참조값을 List 인터페이스 type의 지역변수 nums에 담기
List<Integer> nums=new ArrayList<Integer>();
nums.add(10);
nums.add(20);
nums.add(30);
for(Integer tmp:nums) {
System.out.println(tmp);
}
System.out.println("-----");
nums.forEach((item)->{
System.out.println(item);
});
}
}
List<Integer> nums=new ArrayList<Integer>();
- ArrayList 타입은 기본 데이터 타입(8종)은 담지 못한다.
- List<int>, List<double>, List<float>, ... 등등은 존재하지 않는다.
- Generic이 클래스가 아니기 때문에 담을 수 없다.
- 그렇다면? 객체에 포장을 해서 담아야 한다.(WrapperClass)
기본 데이터타입의 객체형을 사용해야 한다.
- List에 들어갈 수 있는 타입이 Integer 타입으로 wrapping 되었다.
알아서 객체형으로 포장되므로 그냥 쓰면 된다!
for(Integer tmp:nums) {
System.out.println(tmp);
}
- 확장 for문으로 작성한다. for문 안에는 int를 써도 되고 Interger를 써도 된다.
- 디버그모드에서 보면 배열에 그냥 값이 들어가는 것이 아니라 integer 객체에 포장되어 들어가 있다.
(참조값id 가짐)
nums.forEach((item)->{
System.out.println(item);
});
- forEach 를 사용하면 이렇게 쓸 수 있다. item 을 바로 함수에 넣어준다고 생각하기.
<Car> 클래스 생성
package test.mypac;
public class Car {
//필드
private String name;
//생성자
public Car(String name) {
this.name=name;
}
//메소드
public void drive() {
System.out.println(this.name+" 이(가) 달려요~!");
}
}
<MainClass04>
package test.main;
import java.util.ArrayList;
import java.util.List;
import test.mypac.Car;
public class MainClass04 {
public static void main(String[] args) {
//1. Car type을 저장할 수 있는 ArrayList 객체를 생성해서
//참조값을 List 인터페이스 type 지역변수 cars에 담아 보세요.
List<Car> cars=new ArrayList<>();
//2. Car 객체(3개)를 생성해서 List 객체에 저장해 보세요.
cars.add(new Car("소나타"));
cars.add(new Car("프라이드"));
cars.add(new Car("아반떼"));
//3. 반복문 for문을 이용해서 List 객체에 저장된 모든 Car 객체의 drive() 메소드를 순서대로 호출해보세요.
for(Car tmp:cars) {
tmp.drive();
}
System.out.println("--- 기본 for문 ---");
for(int i=0; i<cars.size(); i++) {
cars.get(i).drive();
}
System.out.println("--- Consumer 인터페이스를 활용하면 ---");
cars.forEach((item)->{
item.drive();
});
}
}
- Car 클래스. 생성자에서 name을 만들어서 → 필드에 전달 → 메소드에 전달
List<Car> cars=new ArrayList<>();
- List에 car 객체를 담겠다는 의미미으로 generic< > 에 car를 넣어주기
- new Car 한 객체(의 참조값)를 ArrayList에 하나씩 저장!
Car e=new Car();
- 코딩이 잘 안 되면 대입연산자를 떠올리기.
- 그런데 저 경우에는 에러가 난다.
Car에 기본 생성자가 없고, String 타입 매개변수를 필요로 하는 생성자만 있기 때문이다.
cars.add(new Car("소나타"));
- 이렇게 생성자에 string 타입을 전달해 주어야만 생성할 수 있다.
for(Car tmp:cars) {
tmp.drive();
}
- 확장 for문 작성하기. 임시변수 tmp
- new를 3번 해서 각각의 car 객체의 필드에 저장된 값이 다르기 때문에
똑같은 메소드를 사용해도( drive(); ) 다른 값이 나온다.
<Member> 클래스 생성
package test.mypac;
public class Member {
public int num;
public String name;
public String addr;
/*
* 기본 생성자도 필요하다면 정의할 수 있다.
* 생성자는 다중정의가 가능하다.
* 따라서 어떤 객체를 생성하는 방법이 여러가지가 될 수도 있다는 것이다.
*/
public Member() {}
//필드에 저장할 값을 전달받는 생성자
public Member(int num, String name, String addr) {
this.num=num;
this.name=name;
this.addr=addr;
}
}
- 필드 3개, 2종류의 생성자가 있는 클래스 생성
<MainClass05>
package test.main;
import java.util.ArrayList;
import java.util.List;
import test.mypac.Member;
public class MainClass05 {
public static void main(String[] args) {
//1. Member 객체를 담을 수 있는 ArrayList 객체를 생성해서 참조값을 members 라는 지역변수에 담아 보세요.
List<Member> members=new ArrayList<>();
//2. 3명의 회원정보를 Member객체에 담아 보세요.(Member객체가 3개 생성되어야 함)
Member m1=new Member();
m1.num=1;
m1.name="바나나";
m1.addr="서울";
Member m2=new Member(2,"딸기","부산");
Member m3=new Member(3,"복숭아","대전");
//3. 위에서 생성된 Member 객체의 참조값을 members List 객체에 모두 담아 보세요.
members.add(m1);
members.add(m2);
members.add(m3);
/*
* 4. members List 객체에 담긴 내용을 이용해서 회원 목록을 아래와 같은 형식으로
* 반복문 돌면서 출력해 보세요.
*
* 번호: 1, 이름: 바나나, 주소: 서울
* 번호: 2, 이름: 딸기, 주소: 부산
*
*/
for(Member tmp:members) {
System.out.println("번호: "+tmp.num+", 이름: "+tmp.name+", 주소: "+tmp.addr);
}
System.out.println("---기본 for문---");
for(int i=0; i<members.size(); i++) {
System.out.println("번호: "+members.get(i).num+", 이름: "+members.get(i).name+", 주소: "+members.get(i).addr);
}
}
}
- 클래스명은 대문자, 필드명/메소드명/매개변수는 소문자로 시작하는 것이 일반적이다.
Member m1=new Member();
m1.num=1;
m1.name="바나나";
m1.addr="서울";
- 디폴트 생성자를 사용해 객체를 생성하면 0, null, null로 나오므로 하나씩 넣어주어야 한다.
(필드에 직접 접근하는 것은 대부분 막혀있지만, public으로 되어 있는 필드라면 직접 값을 넣을 수 있다.)
Member m1=new Member(1, "바나나", "서울");
- 대신 이렇게 작성할수도있다. (객체를 생성하면서 바로 필드 값 전달)
- add에는 member타입의 값을 넣어주어야 한다.
- members.add(); 가 종료된 후 arrayList 타입 members 배열 안에 각각 m1,m2,m3에서 참조한 값이 들어갔다.
(members[0] 의 값과 m1의 참조값이 id=40으로 동일한 것 참고!)
- for문 안에서 tmp가 members를 하나씩 순서대로 참조하고 있다.
- ArrayList 객체는 어떤 데이터를 순서 있게 관리하고 싶을 때 사용한다.
즉, 순서가 중요한 데이터를 저장하고자 할 때 사용한다.
<MainClass06> : HashMap
package test.main;
import java.util.HashMap;
/*
* java에서 어떤 데이터를 key:value의 쌍으로 관리하고 싶으면 HashMap객체를 사용한다.
* key의 generic도 마음대로 지정할수있지만 보통 String type으로 한다.
* value의 generic은 그때그때 다르지만 value가 여러가지 type이면 Object로 지정한다.
*/
public class MainClass06 {
public static void main(String[] args) {
/*
* 번호:1, 이름:바나나, 남자여부:false (숫자,문자,불리언)
*/
HashMap<String, Object> map1=new HashMap<>();
map1.put("num", 1);
map1.put("name", "바나나");
map1.put("isMan", false);
int num=(int)map1.get("num");
String name=(String)map1.get("name");
boolean isMan=(boolean)map1.get("isMan");
//동일한 key 값으로 다시 담으면서 수정
map1.put("name", "무화과");
//특정 key 값으로 담긴 내용 삭제, 성공하면 true 실패하면 false 리턴
map1.remove("isMan");
//모두 삭제
map1.clear();
}
}
- java의 HashMap 객체를 사용하면 javascript의 object와 같이 key:value 형태로 데이터를 관리할 수 있다.
- 순서가 없는 데이터의 관리에 적합하다.
- 생성자는 3가지 종류가 있는데, 기본을 제일 많이 쓴다.(아무 전달값 없이)
- 입력하면 <K, V>가 자동완성된다. HashMap도 generic class가 있다.
- java에서 어떤 데이터를 key:value의 쌍으로 관리하고 싶으면 HashMap객체를 사용한다.
- java에서는 키 값도 마음대로 지정할 수 있다.
- key의 generic도 마음대로 지정할 수 있지만 보통 String type으로 한다.
- value의 generic은 그때그때 다르지만 value가 여러가지 type이면 보통 Object로 지정한다.
→ 이유는 Object 타입으로 하면 모든 타입의 값을 넣을 수 있으므로!
.put : 각각의 key, value 값을 대입하는 메소드 (값 넣어주기)
.containsValue : 안에 그값이 들어있는지 확인해서 불리언을 리턴하는 메소드
.getOrDefault : 특정 키값으로 저장된 값을 가지고오는 메소드
.putIfAbsent : 만약 그 값이 없다면 넣는 메소드
- String key="num", "name", "isMan" → String type 만 가능
- Object value=1, "바나나", false → 모든 타입이 전부 들어갈 수 있다!
(사실 값이 그대로 들어가는 건 아니고 참조 데이터타입으로 포장boxing되어서 들어가는 것)
.get : key값을 넣어주면 object 타입으로 리턴한다.(저장되어 있는 값 참조하기)
int num=(int)map1.get("num");
String name=(String)map1.get("name");
boolean isMan=(boolean)map1.get("isMan");
- 하지만 object 타입이 필요한 것이 아니므로 int 타입으로 받아준다.
→ object타입은 int에 담길 수 없다. 따라서 casting 과정 필요! (더 좁은 범위의 타입으로 바꾸어준다)
(object 타입을 사용하면 저장할 때는 편하지만, 가지고 올 때 캐스팅의 번거로움이 있다.)
ArrayList → .add() .get() .size()
HashMap → .put() .get()
- 이 정도를 제일 많이 쓴다. 사실 수정하거나 삭제할 일은 거의 없다.
- 저장 / 참조하는 경우가 대부분. 대부분의 데이터를 read only(읽기 전용)로 사용한다.
- HashMap도 클래스 설명에 들어가보면 타입으로 받을 수 있는 부모클래스와 인터페이스가 많다.(hashmap 클래스 설명)
- ArrayList - List 의 관계와 마찬가지로 HashMap - Map, Map 인터페이스 타입으로 받아서 많이 쓴다.
(put, get, clear 등도 Map 인터페이스 안에 들어있는 메소드이다)
- HashMap의 key는 거의 String 타입 고정이라고 생각하면 된다.
'국비교육(22-23)' 카테고리의 다른 글
19일차(1)/java 퀴즈 : HashMap 활용 예제 (0) | 2022.11.01 |
---|---|
[참고] 이클립스 2개로 git 저장소 clone 연습 (0) | 2022.11.01 |
18일차(2)/java(21) : Generic Class (0) | 2022.10.31 |
18일차(1)/java(20) : 추상 클래스, 인터페이스 정리 / 람다식 (0) | 2022.10.31 |
17일차(4)/java(19) : Interface (0) | 2022.10.30 |