Java 8 Stream : map 함수

최근에 회사에서 새로운 프로젝트를 진행하면서, 사실 저는 별로 Java를 선호하는 사람은 아니었습니다만 Java 8을 써보게 되면서 완전히 Java의 세계로 빠져들게 되었습니다.
물론 아직도 쓸데없이 복잡한 syntax들이 있긴 하지만, 그래도 정말로 최신 language에 뒤지지 않는 좋은 기능들을 많이 탑재하고 있었고, 가히 Java 역사상 가장 큰 major update라고 할만 하다는 생각이 들었습니다 🙂

어쨌든 많은 update들 중 여기서 살펴볼 항목은 Stream이라는 새로운 형태의 자료구조입니다. 만약 분산처리에 익숙하신 분들이라면 Spark를 통해서 이미 익숙한 개념일텐데요, 이 개념을 통해서 아주 획기적인 변화를 가져올 수 있습니다.

여기서 사용할 예제는 0에서 9까지의 정수 리스트가 주어졌을 때, 각 원소에 10씩을 더해서 새로운 리스트를 만드는 것입니다. 일단 0에서 9까지의 정수 리스트를 클래식한 방법으로 만들어 보겠습니다.

List integers = new ArrayList<>();
for (int i=0; i<10; i++) {
integers.add(i);
}

이렇게 되면 integers에는 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]의 숫자가 저장되게 됩니다. 기존 문법으로는 새로운 리스트를 만드려면,

  1. 새로운 `ArrayList`를 만든다.
  2. `for`문을 돌면서 각 원소의 값을 10씩 더한 후 `add`한다.

이렇게 했어야 했습니다. 하지만 Stream을 이용하면 얼마나 간단하고 직관적이어지는지 보시죠.

List newIntegers = integers.stream().map(i -> i + 10).collect(Collectors.toList());

일단은 list인 integersstream()함수를 통해서 Stream형태로 바꾸고, 그 다음에 map함수를 통해서 list의 각 원소 i에 대해서 10씩 더해서 마지막에 collect를 하라는 명령입니다. 이렇게 하면 결과값은 [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]로 우리가 원하는 값이 나오게 됩니다.

어떻게 보면 Stream을 이용한 가장 간단한 예제를 살펴봤는데요, 이것으로 얼마나 많은 일들을 할 수 있는지 기대해도 좋습니다 🙂

Java에서 Json 다루기

Json(JavaScript Object Notation)은 기계와 인간이 소통하기에 가장 적합한 형태의 데이터 표시기법 중의 하나입니다. 특히 요즘과 같이 웹이 모든 일상을 지배하고 있는 이 시점에서 통일된 데이터 표시 규격은 너무나도 중요한 컨셉이지요. 그런 측면에서 Json은 어느 프로그래밍 언어를 사용하든 반드시 다루는 방법을 알고 계셔야 한다고 생각합니다. (참고 : http://www.json.org/json-ko.html)

제가 이번 예제에서 사용할 라이브러리는 jackson 이라는 가장 유명한 java 라이브러리 중 하나입니다. 일단 Json으로 표시할 데이터를 만들기 위해서 Java에서 class를 먼저 만들어 보도록 하겠습니다.

public class Person {

  private String name;
  private int age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

}

Person이라는 클래스를 만들었는데요, 2개의 field를 가지고 있습니다. 이름과 나이가 그것입니다. 그렇다면 이제 실제로 클래스를 만들고 이름으로 “Jacob”을, 나이로 27세를 입력하여 Json string으로 출력해 보도록 하겠습니다.

@Test
public void testWritePojoAsJsonString() {
  Person person = new Person();
  person.setName("Jacob");
  person.setAge(27);
  try {
    System.out.println(objectMapper.writeValueAsString(person));
  } catch (JsonProcessingException e) {
    e.printStackTrace();
  }
}

Pojo를 Json string으로 바꿔주는 함수가 바로 writeValueAsString이라는 함수인데요, 이 함수는 JsonProcessingException을 던지기 때문에 try catch를 사용하시든지 함수 자체에서 throw시키시든지 하셔야 합니다. 위의 함수를 실행했을 때 아래와 같이 출력됩니다.

{"name":"Jacob","age":27}

그러면 이제 저 Json string을 다시 Pojo로 바꾸고 싶으면 어떻게 하면 될까요?

@Test
public void testReadJsonStringAsPojo() {
  Person person;
  try {
    person = objectMapper.readValue("{\"name\":\"Jacob\",\"age\":27}", Person.class);
  } catch (IOException e) {
    e.printStackTrace();
    return; // When failed, quit the test
  }
  Assert.assertNotNull(person);
  Assert.assertEquals(person.getName(), "Jacob");
  Assert.assertEquals(person.getAge(), 27);
}

그것은 위와 같이 readValue라는 함수를 통해서 해당 Json 문자열이 어떤 class로 변환되면 되는지 명시해주면 됩니다. 이때도 마찬가지로 IOException을 handle해 주셔야 합니다. 가장 아래쪽의 3개의 Assert문을 통해서 Pojo가 제대로 생성되었음을 확인할 수 있습니다.

이번 예제에서는 가장 진짜 기본중의 기본기를 다뤘지만, 정말 필수적으로 알아두셔야 할 컨셉이고, 또한 이를 바탕으로 많은 고급 기능들을 구현해 나가실 수 있습니다 🙂