[Java] - 입력, 콜렉션, 정렬

김민우·2023년 2월 28일
1

입력

콘솔창에서 입력받는 방법은 아래와 같이 2가지 방식이 있다.
1. Scanner
2. BufferedReader

백준 1000번 - Scanner

class Main {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);

        String input = sc.nextLine();
        String[] inputBits = input.split(" ");

        int n1 = Integer.parseInt(inputBits[0]);
        int n2 = Integer.parseInt(inputBits[1]);
        System.out.println(n1 + n2);

        sc.close();
    }
}

백준 1000번 - BufferedReader

class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        st = new StringTokenizer(br.readLine());
        int n1 = Integer.parseInt(st.nextToken());
        int n2 = Integer.parseInt(st.nextToken());
        System.out.println(n1 + n2);
    }
}

-> BufferedRader 를 사용해서 입력을 받을 때는 보통 StringTokenizer 클래스를 같이 이용한다. br.raedLine()으로 한 줄 입력을 받고 st.nextToken()으로 띄어쓰기 기준으로 다음 문자열을 받아온다.

콜렉션 프레임워크

대표적인 콜렉션 프레임워크인 List<> 와 HashMap<>에 대해서 알아볼것이다.

List

List<>는 데이터를 삽입하는게 편리하다. but 데이터를 꺼내는것은 불편하다. 그 이유는 데이터를 중간에 삽입하거나 삭제를 시키면 순서가 꼬이게 때문이다.

  • 특징으로는 순서가 보장이 된다.
  • list.add(데이터)
  • list.get(index)
  • list.remove(index)

int[] 와의 차이점
int[]와 List<> 모두 장바구니에 비교를 하겠다. int[]는 장바구니의 크기가 정해져 있는것이고 List<>는 장바구니의 크기가 동적으로 늘어났다가 줄었다한다.

예시 코드

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

        //콜렉션 프레임워크 중 하나인 ArrayList<> 사용
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println("크기 : " + list.size());
        list.add(4);
        System.out.println("크기 : " + list.size());
    }
}

배열의 정렬, List<>의 정렬

class Main {
    public static void main(String[] args) {
        int[] arr = new int[3];
        arr[0] = 10;
        arr[1] = 50;
        arr[2] = 5;
        Arrays.sort(arr);
        
        List<Integer> list = new ArrayList<>();
        list.add(50);
        list.add(20);
        list.add(4);
        Collections.sort(list);
    }
}
  • 배열의 정렬은 Arrays.sort(배열)을 사용한다.
  • List<>의 정렬은 Collections.sort(리스트)를 사용한다.
  • 2개의 정렬 모두 오름차순 정렬이 default이다.
  • List<>의 내림차순 정렬Collections.sort(리스트, Collections.reverseOrder()
  • 배열 내림차순 정렬은Arrays.sort배열, Collections.reverseOrder()를 한다. 이때 배열은 int[] 배열이 아닌, Integer배열이여한다. 기본형 배열이 아닌, 객체 배열이여한다.

HashMap

HashMap은 데이터를 넣을때 Key-Value 형태로 넣기 때문에 데이터 삽입이 조금 불편한다. but 데이터를 꺼내올땐 Key값으로만 찾기 때문에 편리하다.

  • 순서 보장이 되지 않는다.
  • map.put(key, value)
  • mpa.get(key)
  • map.keySet() -> 모든 key를 Set<Key자료형>으로 반환한다.

예시 코드

public class Main {

    public static void main(String[] args) {
        Map<Integer, Person> map = new HashMap<>();
        map.put(1,new Person("홍길동",23, 175));
        map.put(2, new Person("김영순", 20, 165.5));

        System.out.println(map.get(2));
    }
}
class Person{
    String name;
    int age;
    double cm;

    public Person(String name, int age, double cm) {
        this.name = name;
        this.age = age;
        this.cm = cm;
    }
}
  • 위의 예제 처럼 Value에 Class가 들어갈수도 있다. 이런 점을 활용하면 정보를 효율적으로? 저장할수있다.

정렬

  1. 기본정렬
  2. stream 을 이용한 정렬

-> 정렬에 대한 많은 알고리즘이 있지만 자바에서 기본적으로 제공해주는 정렬 알고리즘을 이요하자. 정렬에 대해서는 시간복잡도가 O(NlogN)인 알고리즘을 찾아봐서 한번쯤은 구현해보자.


기본형 정렬 - Arrays.sort()

public class Main {

    public static void main(String[] args) {
        Integer[] array = new Integer[]{50,10,20,-3};
        //오름차순
        Arrays.sort(array);
        Arrays.sort(array,(a,b) -> a-b);
        //내림차순
        Arrays.sort(array, (a,b) -> b-a);
        
        //확인
        for (int x : array) {
            System.out.print(x + " ");
        }
    }
}
  • int[] 에서 Arrays.sort(array, Collections.reverseOrder()) 는 안된다.
  • int[] 내림차순 정렬을 하려면 Arrays.sort(array, Comprator)에서 Comparator를 구현해야한다. 구글링 해보자.

참조형(=객체) 정렬 - Collections.sort()

public class Main {

    public static void main(String[] args) {
        List<Integer> list =new ArrayList<>();
        list.add(100);
        list.add(10);
        list.add(-5);
        //오름차순 정렬 - 2가지 방식
        Collections.sort(list)
        Collections.sort(list, (data1, data2) -> data1>data2? 1 : -1);
        //내림차순 정렬
        Collections.sort(list, (data1, data2) -> data1>data2? -1 : 1);
    }
}

stream을 이용한 정렬1(Integer[])

public class Main {
    public static void main(String[] args) {
        Integer[] array = new Integer[]{50,10,20,-3};

        List<Integer> collect = Arrays.stream(array)
                .sorted((a, b) -> a - b)
                .collect(Collectors.toList());

        for(int x: collect){
            System.out.println(x);
        }
    }
}

stream을 이용한 정렬1(List<타입>)

public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(100);
        list.add(10);
        list.add(5);
        
        //오름차순은 (a,b) -> a-b
        //내림차순은 (a,b) -> b-a
        List<Integer> collect = list.stream()
                .sorted((a, b) -> a - b)
                .collect(Collectors.toList());

        for(int x: collect){
            System.out.println(x);
        }
    }
}

stream을 이용한 정렬1(List<클래스 타입>)
-> 코드업 3004번

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());

        //입력
        st = new StringTokenizer(br.readLine());
        List<Data> list =new ArrayList<>();
        for (int i = 0; i < n; i++) {
            int num = Integer.parseInt(st.nextToken());
            list.add(new Data(0, num));
        }

        //내림차순 정렬 후,순서를 부여한다.
        List<Data> sort_list = list.stream()
                .sorted((e1, e2) -> e1.num - e2.num)
                .collect(Collectors.toList());
        for(int i=0; i<n; i++){
            sort_list.get(i).id = i;
        }

	     //출력
        for(Data data: list){
            System.out.print(data.id + " ");
        }

    }
}
class Data{
    int id;
    int num;

    public Data(int id, int num) {
        this.id = id;
        this.num = num;
    }
}
  • sort_list 와 list 는 동일한 객체를 가리키는 변수이다.
  • stack 메모리에 sort_list, list 라는 변수가 있는데 모두 heap 메모리에 있는 ArrayList<>()를 가리킨다.
  • 코드업 3004번 객체 공유하는거 좀 더 알아보자.
  • 하단에 업데이트 했다.

코드업 3004번 메모리 공유

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

        //1. 제네릭 타입으로 Person 객체 넣고 주소값 비교
        List<Person> list = new ArrayList<>();
        list.add(new Person(50, "김김"));
        list.add(new Person(30,"ㅁㅁㅁ"));
        list.add(new Person(10, "holy"));

        List<Person> list_sorted = list.stream()
                .sorted((a, b) -> a.id - b.id)
                .collect(Collectors.toList());
        System.out.println(list.hashCode()+" / " +list);
        System.out.println(list_sorted.hashCode() + " / " + list_sorted);

        //2. 제네릭 타입으로 기본 자료형 넣고 주소값 비교
        List<Integer> a = new LinkedList<>();
        a.add(10);
        a.add(30);
        a.add(-3);
        List<Integer> a_sorted = a.stream().sorted().collect(Collectors.toList());
        System.out.println(a.hashCode());
        System.out.println(a_sorted.hashCode());

    }
}
class Person{
    int id;
    String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }
}
  • 확인 결과, List<Person클래스>은 그 안의 값이 new 연산을 통해서 heap 메모리에 저장되어서 그안의 값을 공유하고 리모컨은 각각 생성되는 것 같다. 즉, stack 메모리에 변수는 2개 이지만 각 변수가 가리키고 있는 List<Person클래스>의 객체는 동일하다.
  • 반면, List<Integer자료형>와 같은 값 타입을 넣었을 때는 List안에 넣는 값이 객체가 아니라 값이기 때문에 전부 stack 메모리에 형성되어서 공유하지 않는것같다.




마무리

  • stream에 대해서 조금 더 공부해보자.

0개의 댓글

관련 채용 정보