Scribbling

[Java Basics2] 이것이 JAVA다 내용 정리 본문

Computer Science/Java

[Java Basics2] 이것이 JAVA다 내용 정리

focalpoint 2023. 2. 13. 10:23

 

 

5장

1. ==과 !=

기본 타입의 경우 값을 비교하지만, 참조 타입의 경우는 주소값을 저장하므로 ==로 비교하면 같은 객체인지를 확인한다. 

참조 타입 변수는 null을 가질 수 있다.

null과의 비교는 == 혹은 !=를 사용함.

2. 배열의 생성

char[] chars = {
            'a', 'b', 'c', 'a'
        };

3. 2차원 배열

int[][] scores = new int[5][];

 

6장

1. 클래스

- 하나의 소스 파일에 소스 파일명과 동일한 클래스만 public class로 사용 가능함

- 여러 개의 클래스를 선언한 소스 파일을 컴파일하면 클래스 선언 수만큼 바이트코드 파일(.class)이 생김

- 흔히 자바 프로그램은 하나의 실행 클래스와 여러 개의 라이브러리 클라스로 이루어짐

2. 생성자

여러개의 생성자를 구현하는 경우, 하나의 생성자에 모든 로직을 구현하고 이 생성자를 이용하는 것이 용이하다.

this(model, color, 250);

3. 패키지

패키지는 주로 개발 회사의 도메일 이름 역순+프로젝트 명으로 짓는다.

같은 패키지의 클래스는 사용 가능하나, 다른 패키지의 클래스를 사용하려면 import해야 한다.

import 문은 하위 패키지를 포함하지 않는다.

4. Static

Static field와 Static Method는 instance field나 instance method를 사용할 수 없다. 만약 필요한 경우에, 내부에서 객체를 생성하는 방법이 필요하다.

public class Main {
    public static void main(String[] args) {
        
        int[] arr = {1, 2, 3};
        Main obj = new Main();
        System.out.println(obj.sum(arr));

    }
    public int sum(int... values) {
        int ret = 0;
        for (var val : values) {
            ret += val;
        }
        return ret;
    }

}

 

7장

1. instanceof

        String str = "aabbcc";
        Boolean flag = str instanceof String;
        out.println(flag);

 

8장

1. 인터페이스

import java.util.*;
import java.util.stream.Collectors;

import static java.lang.System.out;

public class Main {

    public static void main(String[] args) {

        RemoteControl rc = new Television();
        rc.setVolume(30);
        rc.setMute(true);
        rc.setMute(false);

        

    }
}
public interface RemoteControl {
    public static final int MAX_VOLUME = 50;
    public static final int MIN_VOLUME = 0;
    public void turnOn();
    void setVolume(int volume);

    default void setMute(boolean mute) {
        if (mute) {
            setVolume(MIN_VOLUME);
        } else {
            System.out.println("UnMuted");
        }
    }

}
public class Television implements RemoteControl {
    private int volume = 0;
    private int lastVolume = 0;
    @Override
    public void turnOn() {
        System.out.println("TV On");
    }

    @Override
    public void setVolume(int volume) {
        this.volume = volume;
        System.out.println("volume set: " + volume);
    }

    @Override
    public void setMute(boolean mute) {
        if (mute) {
            this.lastVolume = this.volume;
            System.out.println("Muted");
            setVolume(RemoteControl.MIN_VOLUME);
        } else {
            System.out.println("Unmuted");
            setVolume(this.lastVolume);
        }
    }
}
public class Audio implements RemoteControl {
    private int volume = 0;
    private int lastVolume = 0;
    @Override
    public void turnOn() {
        System.out.println("Audio On");
    }

    @Override
    public void setVolume(int volume) {
        this.volume = volume;
        System.out.println("volume set: " + volume);
    }
}

 

 

9장

1. 중첩 클래스 / 인터페이스

중첩 인터페이스는 UI 프로그램에서 이벤트 처리 목적으로 많이 활용된다.

public class Button {
    private ClickListener clickListener;
    public static interface ClickListener {
        void onClick();
    }

    public void setClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;
    }

    public void click() {
        this.clickListener.onClick();
    }

}
public class Main {


    public static void main(String[] args) {

        Button btn1 = new Button();
        class OkListener implements Button.ClickListener {
            @Override
            public void onClick() {
                System.out.println("Ok 버튼 클릭");
            }
        }
        btn1.setClickListener(new OkListener());
        btn1.click();

        Button btn2 = new Button();
        btn2.setClickListener(new Button.ClickListener() {
            @Override
            public void onClick() {
                System.out.println("Cancel 버튼 클릭");
            }
        });
        btn2.click();


    }
}

 

 

11장

1. 예외 처리

- Exception: 컴파일러가 예외 처리 코드 여부를 검사하는 예외

- Runtime Exception: 컴파일러가 예외 처리 코드 여부를 검사하지 않는 예외

public class Main {

    public static void printLength(String str) {
        try {
            System.out.println(str.length());
        } catch (NullPointerException e) {
            e.printStackTrace();
        } finally {
            System.out.println("");
        }
    }

    public static void main(String[] args) {

        printLength(null);


    }
}

 

12장

1. Object Methods

Object의 equals() 메소드는 재정의를 통해 동등 비교용으로 사용된다.

구체적으로, 자바는 두 객체가 동등함을 비교할 때 hashcode()와 equals() method를 같이 사용한다. 우선 hashcode()가 같은 정수를 return하는지 확인하고 그 다음 equals() method가 true를 return하는지 확인한다. 때문에 두 method를 같이 구현해야 한다.

toString() 메소드는 객체의 문자 정보를 리턴한다.

 

2. Record

레코드는 변수의 타입과 이름을 이용해서 private final 필드를 자동 생성하고, 생성자 및 getter 메소드가 자동으로 추가된다. (+hashcode, equals, toString methods)

public class Main {

    public record Member(String id, String name, int age) {

    }

    public static void main(String[] args) {

        Member m = new Member("123", "Morgan", 29);
        System.out.println(m.id());
        System.out.println(m.toString());


    }
}

 

3. Annotation

어노테이션은 클래스 또는 인터페이스를 컴파일/실행 할 때 어떻게 처리할지 알려주는 설정이다.

예컨대 @Override는 컴파일러가 메소드 재정의 검사를 하도록 설정한다.

public class cls {
    @Main.PrintAnnotation
    public static void method1() {
        System.out.println("method1");
    }

    @Main.PrintAnnotation("*")
    public static void method2() {
        System.out.println("method2");
    }

}
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Stack;

public class Main {
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PrintAnnotation {
        String value() default "-";
        int number() default 15;
    }


    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {

        Method[] declaredMethods = cls.class.getDeclaredMethods();
        for(Method method: declaredMethods) {
            PrintAnnotation pat = method.getAnnotation(PrintAnnotation.class);
            printLine(pat);
            method.invoke(new cls());
            printLine(pat);
        }

    }

    private static void printLine(PrintAnnotation pat) {
        if(pat != null) {
            int number = pat.number();
            for (int i=0; i<number; i++) {
                String val = pat.value();
                System.out.print(val);
            }
            System.out.println();
        }
    }
}

 

13장

1. Generic Types

public class Main {

    public static <T extends Number> void print(T t1, T t2) {
        System.out.println(t1);
        System.out.println(t2);
    }

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {

        print(10, 20);


    }
}

 

2. Limited, Wildcard Type Parameters

    public static void method1(Applicant<?> app) {
        
    }
    public static void method2(Applicant<? extends Student> app) {

    }
    public static void method3(Applicant<? super Employee> app) {

    }

method1: Any type is allowed for Applicant class

method2: Student, High Schooler, and Middle Schooler classes are allowed

method3: Employee, Person are allowed

 

15장

1. List Collection

<Methods>

boolean add(E e)

void add(int index, E element)

set (int index, E element)

boolean contains(Object o)

E get(int index)

isEmpty()

int size()

void clear()

E remove(int index)

boolean remove(Object o)

 

To initiate an ArrayList for different types.

List list = new ArrayList();

 

2. Set Collection

<Methods>

boolean add (E e)

boolean contains(Object o)

isEmpty()

Iterator<E> iterator()

int size()

void clear()

boolean remove (Object o)

 

Iteration

Set<String> set = new HashSet<>();
Iterator<String> it = set.iterator();

while (it.hasNext()) {
	String e = it.next();
    if (e.equals("XXX")) {
    	it.remove();
    }
}

 

3. Map Collection

<Methods>

V put(K key, V value)

boolean containsKey(Object key)

boolean containsValue(Object value)

Set<Map.Entry<K,V>> entrySet()

V get(Object key)

boolean isEmpty()

Set<K> keySet()

int size()

Collection<V> values()

void clear()

V remove(Object key)

 

4. Comparable & Comparator

- To sort a user-defined class; use "Comparable"

class Person implements Comparable<Person> {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person person) {
        int val = this.name.compareTo(person.name);
        if (val != 0) return val;
        return this.age - person.age;
    }
}


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

        TreeSet<Person> t = new TreeSet<>();
        t.add(new Person("이이이", 27));
        t.add(new Person("전전전", 28));
        t.add(new Person("김김김", 28));
        t.add(new Person("김김김", 29));
        t.add(new Person("김김김", 30));

        for (var p: t) {
            System.out.println(p.name + p.age);
        }
    }
}

 

- In case you cannot change the class; use Comparator

class Person{
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class PersonComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        int val = o1.name.compareTo(o2.name);
        if (val != 0) return val;
        return o1.age - o2.age;
    }
}


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

        TreeSet<Person> t = new TreeSet<>(new PersonComparator());
        t.add(new Person("이이이", 27));
        t.add(new Person("전전전", 28));
        t.add(new Person("김김김", 28));
        t.add(new Person("김김김", 29));
        t.add(new Person("김김김", 30));

        for (var p: t) {
            System.out.println(p.name + p.age);
        }
    }
}

 

5. Stack

<Methods>

push(E item)

pop()

 

6. Queue

<Methods>

offer(E e)

poll()

 

7. Immutable Collections

        List<String> l1 = List.of("A", "B", "C");

        List<String> l2 = List.copyOf(l1);

 

16장

1. 함수형 프로그래밍 (Functional Programming)은 함수를 정의하고 이 함수를 데이터 처리부로 보내 데이터를 처리하는 기법이다.

함수형 인터페이스를 정의하면, 해당 인터페이스에 익명 함수를 전달하는 방식으로 데이터에 다양한 함수를 적용 가능하다.

함수형 인터페이스

@FunctionalInterface
interface Calculable {
    // abstract method
    void calculate(int x, int y);
}



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

        execute((x, y) -> {
            System.out.println(x+y);
        }, 3, 4);
        execute((x, y) -> {
            System.out.println(x*y);
        }, 3, 4);

    }

    public static void execute(Calculable calculable, int x, int y) {
        calculable.calculate(x, y);
    }
}

class Button {
    @FunctionalInterface
    public static interface ClickListener {
        void onClick();
    }

    private ClickListener clickListener;

    public void setClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;
    }

    public void click() {
        clickListener.onClick();
    }

}


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

        Button btnOk = new Button();
        btnOk.setClickListener(() -> {
            System.out.println("Ok");
        });
        btnOk.click();

        Button btnC = new Button();
        btnC.setClickListener(() -> {
            System.out.println("cancel");
        });
        btnC.click();

    }


}

 

 

17 장

1. Stream

1) 내부 반복자를 사용하여 처리 속도가 기본적으로 빠르며, 병렬 처리를 지원함

2) 람다식으로 많은 기능 지원

3) 파이프라인의 형성

 

2. Stream Example

class Student {
    public String name;
    public int score;

    public Student (String name, int score) {
        this.name = name;
        this.score = score;
    }

}

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

        List<Student> list = Arrays.asList(
                new Student("홍길동", 97),
                new Student("김김김", 3),
                new Student("이이이", 100),
                new Student("전전전", 99)
        );

        double avg = list.stream()
                .mapToInt(student -> student.score)
                .average()
                .getAsDouble();

        System.out.println(avg);

    }
    
}

* Array의 Stream 객체

        int[] intArray = {1, 2, 3, 4, 5};
        IntStream is = Arrays.stream(intArray);

 

3. Distinct와 Filter

Distinct는 Unique element만 선별하고

Filter는 특정 조건으로 선별한다.

int[] intArray = {1, 2, 3, 4, 5, 5, 5};
IntStream is = Arrays.stream(intArray);
is.distinct().forEach(System.out::println);

        int[] intArray = {1, 2, 3, 4, 5, 5, 5};
        IntStream is = Arrays.stream(intArray);
        is.filter(n -> n % 2 == 0).forEach(System.out::println);

 

4. 다른 Stream으로 변환하기

list.stream()
.mapToInt(student -> student.score)
.forEach(System.out::println);

map: Object 간의 변환

mapToInt: Object -> IntStream

* IntStream: primitive int stream

mapToObj: int/long/double -> Object

등 다양한 mapping method가 존재하므로 data type에 유념하여 사용하면 된다.

 

요소를 복수 개의 요소로 변환하는 것도 가능하다.

List<String> list2 = Arrays.asList("This is Morgan", "Queue And Stack");
list2.stream()
.flatMap(sentence -> Arrays.stream(sentence.split("")))
.forEach(System.out::println);

 

5. 정렬

Integer, Long 등 Comparable Interface를 구현한 객체는 다음과 같이 정렬 가능하다.

list.stream()
.mapToInt(student -> student.score)
.sorted()
//.sorted(Comparator.reverseOrder())
.forEach(System.out::println);

 

Comparable Interface가 구현되지 않은 객체는 Comparator를 이용하여 정렬한다. (엄밀히 말하면, Comparator Functional Interface에 대입할 람다 함수)

list.stream()
.sorted((s1, s2) -> Integer.compare(s1.score, s2.score))
.mapToInt(student -> student.score)
.forEach(System.out::println);

 

* 참고로 peek는 중간처리 method이고 forEach는 최종처리 method이다 (기능은 동일)

 

6. allMatch(), anyMatch(), noneMatch()

boolean result = list.stream()
                .mapToInt(student -> student.score)
                .allMatch(s -> s % 2 == 0);

 

7. Aggregation; count(), findFirst(), max(), min(), average(), sum(), max(Comparator<T>), min(Comparator<T>)

* orElse를 이용한 default 설정

double avg = is.average().orElse(0.0);
System.out.println(avg);

* reduce

int sum = is.reduce(0, (a, b) -> a + b);

 

8. Collect

List<Student> list2 = list.stream().filter(s->s.name.contains("전")).toList();
Map<String, Integer> map = list.stream().collect(
                Collectors.toMap(
                        s -> s.name,
                        s -> s.score
                )
        );

 

9. groupingBy

class Student {
    public String name;
    public String sex;
    public int score;

    public Student (String name, String sex, int score) {
        this.name = name;
        this.sex = sex;
        this.score = score;
    }

}

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

        List<Student> list = Arrays.asList(
                new Student("홍길동", "남", 97),
                new Student("김김김", "여", 3),
                new Student("이이이", "남", 100),
                new Student("전전전", "남", 99)
        );


        Map<String, List<Student>> map = list.stream().collect(
                Collectors.groupingBy(s->s.sex)
        );
        System.out.println(map.get("남"));
        


    }

}
Map<String, Double> map = list.stream().collect(
                Collectors.groupingBy(
                        s->s.sex,
                        Collectors.averagingDouble(s->s.score)
                )
        );
System.out.println(map.get("남"));

 

10. Parallel Stream

parallelStream() or Parallel()