Java Optional 살펴보기 C#개발자가

Optional 에 대해서 살펴보겠습니다.

대략적인 문법만 살펴봐도 C#의 "Nullable" 와 상당히 유사한 키워드임을 확인 가능하였습니다.

실제로 사용방법에서도 크게 차이는 없었지만 Java Stream의 연산방법 때문인지 sugar? 적인 문법 처리가 덜되서인지 아무래도 Optional문법의 경우 상대적으로 몇가지 불편한 점을 확인할수 있었는데 다른것보다. 데이터의 확인이였습니다.

public class OptionalDemo {

  public static List<Member> memberList = new ArrayList<Member>();

  public static void main(String[] args) {
      memberList.add(new Member(1L, "name1"));
      memberList.add(new Member(2L, "name2"));
      memberList.add(new Member(3L, "name3"));
      memberList.add(new Member(4L, "name4"));
      memberList.add(new Member(5L, "name5"));

      Optional<Member> findById1 = memberList.stream().filter(r -> r.getId() == 2L).findAny();
      Optional<Member> findById2 = memberList.stream().filter(r -> r.getId() == 6L).findAny();

      System.out.println("================= result null check =====================");
      if(findById1 != null){
          System.out.println(findById1.toString());
      }
      else{
          System.out.println("findById1 not found");
      }
      
      if(findById2 != null){
          System.out.println(findById2.toString());
      }
      else{
          System.out.println("findById2 not found");
      }

      System.out.println("================= result isPresent =====================");
      if(findById1.isPresent()){
          System.out.println(findById1.toString());
      }
      else{
          System.out.println("findById1 not found");
      }

      if(findById2.isPresent()){
          System.out.println(findById2.toString());
      }
      else{
          System.out.println("findById2 not found");
      }

      System.out.println("================= result ifPresentOrElse =====================");
      findById1.ifPresentOrElse(f1 -> {
          System.out.println(f1.toString());
      }, () -> {
          System.out.println("findById1 not found");
      });

      findById2.ifPresentOrElse(f2 -> {
          System.out.println(f2.toString());
      }, () -> {
          System.out.println("findById2 not found");
      });

      System.out.println("================= result empty? null? =====================");
      if(findById1.isEmpty()) {
          System.out.println("findById1 not found");
      }

      if(findById2.isEmpty()) {
          System.out.println("findById2 not found");
      }


  }
}

Id, Name을 가지는 Member클레스를 만들고 아이디를 1~5까지 생성하여

findById1 : 2 아이디 찾기 :2번
findById2 : 6 아이디 찾기 :null

null의도를 확인하기 위한 데이터 찾기 를 하였습니다.

대부분의경우 ifPresent 함수를 통한 데이터 확인을 하는 방식으로 데이터를 처리하는 예제가 가장 많았으며 ifPresentOrElse로 동작 함수를 일힘하여 처리 하는 방식도 확인 할 수 있었습니다.

C#과의가장 큰 문법 차이는 C#의 경우 nullable reference타입이 최근에 제공되고 있긴하지만 기본적으로 value타입이 아닌경우는 모두 null값을 가질수 있는 참조 타입임으로 데이터가 null이라면 해당 값에 바로 null을 할당하여 값을 직접 비교하는 방식인 반면.

Java Optional의 경우는 어떠한경우에도 Optional로 Wrapping한 클레스를 감싸야하고 해당 클레스의 get()을 호출하여 데이터를 가져와야하는다는 차이점이 가장크다.

c#의문법을 살펴보면 다음과 같다.

class Program
    {
        static void Main(string[] args)
        {
            List<Member> memberList = new List<Member>
            {
                new Member(1, "name1")
            ,   new Member(2, "name2")
            ,   new Member(3, "name3")
            ,   new Member(4, "name4")
            ,   new Member(5, "name5")
            };

            varById1 = memberList.Find(m => m.Id == 2);
            var findById2 = memberList.Find(m => m.Id == 6);
            //Member? findById1
            //Member? findById2

            System.Console.WriteLine(findById1 != null ? findById1.ToString() : "findById1 not found data");
            System.Console.WriteLine(findById2 != null ? findById2.ToString() : "findById2 not found data");

            if (findById1 == null)
            {
                System.Console.WriteLine("findById1 not found data");
            }

            if (findById2 == null)
            {
                System.Console.WriteLine("findById2 not found data");
            }

        }
    }

최종 할당된데이터는 바로 null check로 데이터를 확인하여 데이터를 출력가능한 구조라서 간편하게 null체크 이후에 데이터를 활용가능하다는 가장 큰차이점이 있다.

다만 값타입일경우는 Java와 마찬가지로 다음과 같은 비슷한 과정을 거쳐야한다.

Nullable<int> i = null;
if (i.HasValue)
{
    Console.WriteLine(i.Value);
}

대부분이 처리 하는데이터가 참조타입의 데이터가 많다는걸 생각하면 다소 아쉬운 부분이지만 이용하거나 사용하는데에는 큰 불편함이 없을것 같다.

--추가...
작성이후에 알게 되었다.
Java의 경우 숫자 형에 대한 Optional형이 따로 존재 하며 다음과 같다.
Stream : Optional
IntStream : OptionalInt
LongStream : OptionalLong
DoubleStream : OptionalDouble

마지막 최종연산인 reduce : 현시점에서 학습은 하지 못햇고 살짝 둘러만봤다. 일종에 누적기로 보이는데 reduce함수형인터페이스역시 순서대로 다음과 같으며 형에 따라 BinaryOperator가 각각존재하며 맞게 사용할수록 성능이 더 우수한것으로 보인다.

BinaryOperator : Stream : 일반객체
IntBinaryOperator : IntStream : Integer
LongBinaryOperator : LongStream : Long
DoubleBinaryOperator : DoubleStream : Double

역시 자린이.. 그냥 보이는데로 순서대로 학습하다보니 깊이를 알지 못하고 막 작성하는경향이 있지만 틀리면.. 누가 지적하면 수정하면되지.. 알고나서도 수정하면되지.. 하는 마음으로 일단 작성하자.

일단 하는게 중요하니..

좋은 웹페이지 즐겨찾기