
1. Object 클래스
1) 특징
① 자바의 모든 객체는 Object 클래스의 인스턴스임
② Object 는 자바에 있는 모든 클래스의 최상위 슈퍼 클래스임
→ 자바의 모든 클래스는 Object 클래스를 상속받게 되어있음
→ 따로 슈퍼클래스를 지정하지 않으면 자동으로 extends Object 상태임
③ Object 클래스에 정의된 메서드는 모든 클래스가 오버라이딩 할 수 있음
* 단, final은 제외
④ 자바의 모든 객체는 Object 타입으로 참조할 수 있음.
→ Object의 배열도 예외가 아님
import java.lang.Object;
class A /*extends Object */{}
class B extends A {}
public class Ex01 {
public static void main(String[] args) {
A ob = new B();
System.out.println(ob.getClass().toString());
B ob2 = (B) ob;
System.out.println(ob.equals(ob2));
Object ob3 = ob; // A
Object ob4 = ob2; // B
System.out.println(ob3.getClass());
System.out.println(ob4.getClass());
System.out.println(ob3.equals(ob4));
}
}
- 참조가 업캐스팅 되어도 객체 자신의 정보는 변하지 않음
import java.util.Comparator;
import java.util.Scanner;
class Test extends Object {
private String str;
public Test(String str) {
this.str = str;
}
public String getStr() {
return str;
}
@Override
public String toString() {
return "비밀";
}
}
public class Ex02 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Test ob = new Test("휴강");
Runtime rt = Runtime.getRuntime();
int[] arr = {2, 7, 8, 4, 6};
Comparator<Double> cmp = (a, b) -> (int)(b - a);
Object[] t1 = { sc, ob, rt, arr, cmp };
Object target = t1;
- 예시 문제) 위의 코드에서, target으로 시작하여 ‘휴강’ 이라는 문자열을 화면에 출력해보기
~ 답 1
System.out.println(((Test)((Object[])target)[1]).getStr());

~ 답 2
Object[] t2 = (Object[])t1;
for(int i = 0; i < t2.length; i++) {
if(t2[i] instanceof Test) {
Test t3 = (Test)t2[i];
System.out.println(t3.getStr());
}
}

2) Object 클래스의 메서드
① toString()
- 객체를 문자열 형태로 변환해서 반환해줌
class MyNumber extends Object {
int num;
public MyNumber(int num) {
this.num = num;
}
@Override
public String toString() {
return String.valueOf(num);
}
* valueOf() 는 static 메서드이기 때문에 객체없이 클래스에서 바로 호출할 수 있음
② equals()
- 서로 다른 두개의 객체가 일치하는지를 비교하여 반환해줌
@Override
public boolean equals(Object obj) {
if(obj instanceof MyNumber) {
return this.num == ((MyNumber)obj).num;
}
return false;
}
}
- this와 obj를 비교하여, 일치하면 true를 반환하고, 아니면 false를 반환함
- 비교대상 obj의 클래스가 같으면 비교함
- 클래스가 다르면 비교할 필요없이 false를 반환
public class Ex03 {
public static void main(String[] args) {
MyNumber n1 = new MyNumber(10);
MyNumber n2 = new MyNumber(10);
System.out.println("n1 : " + n1);
System.out.println("n2 : " + n2);
System.out.println("n1 == n2 : " + (n1 == n2));
// 두 변수가 같은 대상을 바라보는가?
System.out.println("n1.equals(n2) : " + n1.equals(n2));
// 두 변수의 내용이 같은가?
}
}
- new 연산자를 사용했다면, 새로운 공간에 객체를 생성함

2. Collection
1) Collection Framework
: 다수의 데이터를 관리하기 위해 자료를 저장할 수 있는 구조
- 자바는 이 구조를 여러 클래스로 만들어두었고, 편의를 위한 메서드도 준비되어 있음
→ 어떤 종류의 컬렉션이 있는지, 어떻게 사용하는 것인지 익히고, 적재적소에 활용할 수 있도록 연습할 것.
2) 종류
① List : index로 값에 접근하고, 중복을 허용함
* 배열과의 차이점 : 크기가 자동으로 조절됨
② Set : index 개념이 없고, 중복을 허용하지 않음
③ Map : index 대신 key 라는 형식을 이용하여 값(Value)에 접근함
→ key와 value가 매핑 되어있음
→ 이때, key는 중복을 허용하지 않고, value는 중복을 허용함
import java.util.List;
import java.util.Map;
import java.util.Set;
- 각 컬렉션의 특징만을 담고 있는 인터페이스를 import 함
- 이 인터페이스들을 구현(implement) 하여 만들어진 하위 클래스들을 이용함
- ArrayList, HashSet, HashMap
List ob1;
Set ob2;
Map ob3;
3. List
: 크기를 변경할 수 있는 배열
1) 특징
- 배열과 유사하게 사용할 수 있음
- 리스트(및 컬렉션)에는 자료형에 상관없이 모든 데이터를 추가할 수 있음
- 리스트에서 어떤 자료형을 처리할 지를 명시해주는 것이 안전함. → 제네릭 타입
(ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized)

import java.util.ArrayList;
public class Ex05 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
System.out.println("리스트의 크기 : " + list.size());
list.add(10);
list.add(20);
list.add("APPLE");
list.add(20); // 중복된 데이터 추가
System.out.println("리스트의 크기 : " + list.size());
System.out.println(list);
Object v1 = list.get(0); // arr[0]
Object v2 = list.get(1); // arr[1]
System.out.println(v1);
System.out.println(v2);
}
}

~ Human 타입의 클래스 만들기
import java.util.ArrayList;
class Human {
private String name;
private int age;
public Human(String name, int age) {
this.name = name;
this.age = age;
}
public void show() {
System.out.printf("이름 : %s, 나이 : %d살\n", name, age);
}
@Override
public String toString() {
return String.format("이름 : %s, 나이 : %d살", name, age);
}
}
~ 리스트 만들기
public class Ex06 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add(10);
list1.add(20);
list1.add(3.14);
Human ob1 = new Human("이지은", 30);
list1.add(ob1);
System.out.println(list1);

- 배열과 달리 리스트는 서로 다른 자료형의 데이터도 받을 수 있음
ArrayList list2 = new ArrayList();
Human ob2 = new Human("홍진호", 41);
list2.add(ob1);
list2.add(ob2);
System.out.println(list2)

- 이때, ob1은 Object로 업캐스팅이 됨.
- 따라서 객체를 호출하기 위해서는 Human 타입으로 다운캐스팅을 해줘야함.
for(int i = 0; i < list2.size(); i++) {
Human element = (Human)list2.get(i);
element.show();
}

→ 내부 원소(element)가 Object 타입이면, 객체 메서드를 호출하기 위해 일일이 다운캐스팅을 해야함
2) 제네릭 타입
: 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법
- 특정 클래스의 객체만 저장하는 리스트
- 지정한 타입의 클래스가 슈퍼클래스가 됨
- 자바 1.5에서 새로 추가된 문법임
- 배열, 리스트 모두 가능
ArrayList<Human> list3 = new ArrayList<Human>();
list3.add(ob1);
list3.add(ob2);
for(int i = 0; i < list3.size(); i++) {
list3.get(i).show();
} System

3) 향상된 for문
: index를 사용하지 않는 for문
* forEach라고도 하지만, 함수이름과 중복되기 때문에 헷갈릴 수 있음
- Iterable 한 타입에 대해서 적용할 수 있음 (배열 포함)
- 배열, 리스트 모두 가능
for(Human element : list3) {
element.show();
} System.out.println();.out.println();

- list는 forEach 함수가 별도로 존재함 (리스트만 가능)
list3.forEach(element -> element.show());
- 람다식 : (매개변수) -> {실행할 내용}
- list3의 각각의 요소를 element라고 할 때, element.show()를 호출해라.

- toString이 오버라이딩 되어 있다면, System.out.println을 전달할 수도 있음
list3.forEach(System.out::println);
- : :
→ 객체 내부의 println을 찾아서 전달해라.
- list3의 각 요소를 System.out 객체 내부의 println 메서드의 인자로 전달한다.

4) Comparator
- Comparator 인터페이스에는 미구현 추상 메서드가 하나임
→ 함수형 인터페이스
~ Item 클래스 생성
import java.util.ArrayList;
import java.util.Comparator;
class Item {
String name;
int price;
Item(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return String.format("%s : %,d원", name, price);
}
}
~ 비교하는 객체를 만들어서 사용해보기
class MyComparator implements Comparator<Item> {
@Override
public int compare(Item o1, Item o2) {
return o1.price - o2.price;
}
}
- o1.price - o2.price > 0 → o1.price > o2.price
- 반환값이 0보다 큰지 아닌지에 따라서 자리바꿈을 판별한다.
~ 리스트에 값 저장하기
① 정수 리스트
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<Integer>();
ArrayList<Item> list2 = new ArrayList<Item>();
list1.add(2);
list1.add(7);
list1.add(8);
list1.add(4);
list1.add(6);
System.out.println(list1);
list1.sort(null);
System.out.println(list1);

② Item 객체 리스트
list2.add(new Item("오레오", 2000));
list2.add(new Item("몽쉘", 3000));
list2.add(new Item("초코파이", 2500));
list2.add(new Item("오예스", 2700));
list2.add(new Item("빅파이", 2900));
list2.forEach(System.out::println);

- 가격 순 오름차순 정렬
→ MyComparator implement Comparator의 객체를 생성하여 전달
System.out.println("가격 오름차순 정렬");
MyComparator priceCmp = new MyComparator();
list2.sort(priceCmp);
list2.forEach(System.out::println);

- 이름 순 오름차순 정렬
→ 익명 클래스 활용
System.out.println("이름 오름차순 정렬");
list2.sort(new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2) {
return o1.name.compareTo(o2.name);
}
});
list2.forEach(System.out::println);
System.out.println();

- 가격 순 내림차순 정렬
→ 람다식
System.out.println("가격 내림차순 정렬");
list2.sort((o1, o2) -> {
return o2.price - o1.price;
});
list2.forEach(System.out::println);
System.out.println();
- 매개변수가 2개라서 소괄호는 생략 불가능
- 실행 내용과 실행 결과가 한줄이기 때문에 중괄호와 return은 생략할 수 있음

* 배열로 만들었을 경우
~ 정수 비교 기능을 가진 MyIntegerComparator 생성
import java.util.Comparator;
class MyIntegerComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
~ 배열 출력 함수
static void showArray(Integer[] arr) {
System.out.print("[");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
System.out.print(i != arr.length - 1 ? ", " : "]\n");
}
System.out.println();
}
~ 배열 선택정렬 함수
static void mySort(Integer[] arr, MyIntegerComparator cmp) {
for(int i = 0; i < arr.length - 1; i++) {
for(int j = i + 1; j < arr.length; j++) {
if(cmp.compare(arr[i], arr[j]) > 0) {
// if(arr[i] > arr[j])
Integer tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}
~ 메인 함수
public static void main(String[] args) {
Integer[] arr = { 2, 7, 8, 4, 6 };
showArray(arr);
MyIntegerComparator cmp = new MyIntegerComparator();
// list.sort(cmp); // list는 this, 0번째 매개변수
mySort(arr, cmp);
showArray(arr);
}

~ 정렬 예시
① 정수의 정렬
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Ex09 {
public static void main(String[] args) {
Integer[] arr = { 2, 7, 8, 4, 6 };
List<Integer> list1 = Arrays.asList(arr);
System.out.println("list1 : " + list1);
// 오름차순 정렬
list1.sort((a, b) -> a - b);
System.out.println("오름차순 정렬 후 list : " + list1);
// 내림차순 정렬
list1.sort((a, b) -> b - a);
System.out.println("내림차순 정렬 후 list : " + list1);

* 이때, 원본 리스트의 순서를 저장해두고 싶다면, 새로운 리스트에 원본 리스트를 복사해두면 됨.
Integer[] arr = { 2, 7, 8, 4, 6 };
List<Integer> list1 = Arrays.asList(arr);
System.out.println("list1 : " + list1);
// 복사본
List<Integer> list2 = new ArrayList<Integer>(list1);
System.out.println("원본을 복사한 list2 : " + list2);
System.out.println();

② 문자열의 정렬
String[] arr3 = {"나비", "다람쥐", "가방", "라디오"};
List<String> list3 = Arrays.asList(arr3);
// 문자열 오름차순
list3.sort((a, b) -> a.compareTo(b));
System.out.println(list3);
// 문자열 내림차순
list3.sort((a, b) -> b.compareTo(a));
System.out.println(list3);

5) Comparable
public static void main(String[] args) {
String[] arr = { "이지은", "홍진호", "나단비", "유재석", "김종국" };
List<String> list = Arrays.asList(arr);
System.out.println(list);
list.sort(null);
System.out.println(list);

- Comparator를 전달하지 않았는데, 왜 정렬이 되는가?
→ String은 Comparable한 클래스이기 때문임
~ (다른 Item2 와) 비교가 가능한 클래스 Item2 만들기
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Item2 implements Comparable<Item2> {
String name;
int price;
Item2(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return String.format("%s : %,d원", name, price);
}
@Override
public int compareTo(Item2 o) { // Item2의 compareTo
return this.name.compareTo(o.name); // String의 compareTo
}
}
- Item2의 객체 this와 Item2의 또다른 객체 o를 비교하려면, this의 name과 o의 name을 비교하여 그 차이를 int로 반환하면 됨
~ Comparable 객체의 CompareTo 메서드 테스트
ArrayList<Item2> list2 = new ArrayList<Item2>();
list2.add(new Item2("오레오", 2000));
list2.add(new Item2("몽쉘", 3000));
list2.add(new Item2("초코파이", 2500));
list2.add(new Item2("오예스", 2700));
list2.add(new Item2("빅파이", 2900));
System.out.println("원본");
list2.forEach(System.out::println);
System.out.println();
System.out.println("이름순 정렬");
list2.sort(null);
list2.forEach(System.out::println);
System.out.println();


~ 실습 예제) 브랜드별 치킨 정렬하기
- Food 클래스 만들기
import java.util.ArrayList;
import java.util.List;
class Food implements Comparable<Food>{
String brand;
String menu;
int price;
public Food(String brand, String menu, int price) {
this.brand = brand;
this.menu = menu;
this.price = price;
}
@Override
public int compareTo(Food o) {
return o.price - this.price;
}
@Override
public String toString() {
return String.format("%s - %s (%,d원)", brand, menu, price);
}
}
~ Food 객체와 리스트 생성
public static void main(String[] args) {
Food f1 = new Food("굽네치킨", "고추바사삭", 21000);
Food f2 = new Food("BBQ", "황금올리브", 19000);
Food f3 = new Food("굽네치킨", "깐풍치킨", 22000);
Food f4 = new Food("교촌치킨", "허니콤보", 20000);
Food f5 = new Food("KFC", "핫크리스피", 21200);
List<Food> list = new ArrayList<Food>();
list.add(f1);
list.add(f2);
list.add(f3);
list.add(f4);
list.add(f5);
System.out.println("정렬을 하지 않았을 때");
list.forEach(food -> System.out.println(food));
System.out.println();

- 기본정렬 시 가격 내림차순으로 정렬하기
System.out.println("가격 내림차순 정렬");
list.sort(null);
list.forEach(food -> System.out.println(food));
System.out.println();

- 브랜드 기준 오름차순으로 정렬하기
System.out.println("브랜드 오름차순 정렬");
list.sort((o1, o2) -> o1.brand.compareTo(o2.brand));
list.forEach(food -> System.out.println(food));
* 람다식의 괄호와 중괄호를 생략하지 않은 경우
list.sort((o1, o2) -> { return o1.brand.compareTo(o2.brand); });

'JAVA > JAVA Note' 카테고리의 다른 글
| [JAVA Note] 20. 예외 (0) | 2022.11.16 |
|---|---|
| [JAVA Note] 19. Collection (1) | 2022.11.16 |
| [JAVA Note] 17. 추상화 (0) | 2022.11.06 |
| [JAVA Note] 16. 추상클래스 (0) | 2022.11.02 |
| [JAVA Note] 15. 상속 (0) | 2022.11.02 |
댓글