반응형

자바에서 문자열을 처리하는 방법에는 String, StringBuilder, StringBuffer가 있습니다. 

 

시간이 없다면, 맨 아래로..

한 줄로 정리하자면..

이들은 각각 고정된 문자열, 가변적인 문자열, 스레드 안전한 가변적인 문자열을 처리하는 데 사용됩니다.


1. String

먼저, String 클래스는 불변 객체입니다.

이것은 생성된 문자열이 수정되지 않는다는 것을 의미합니다.

String 클래스는 final 키워드가 지정되어 있기 때문에 하위 클래스에서 재정의 할 수 없습니다.

따라서, String 클래스의 메소드들은 문자열을 수정하는 것이 아니라 새로운 문자열을 생성합니다.

예를 들어, String 클래스의 concat() 메소드는 기존 문자열과 다른 문자열을 연결하여 새로운 문자열을 반환합니다.

 

2. String과 StringBuilder, String Buffer의 차이

반면에 StringBuilder와 StringBuffer 클래스는 가변적인 문자열을 처리합니다.

StringBuilder와 StringBuffer는 둘 다 append()와 insert() 메소드를 제공하여 문자열을 수정할 수 있습니다.

또한, StringBuilder와 StringBuffer는 내부 버퍼를 가지고 있으며, 필요에 따라 버퍼 크기를 조정할 수 있습니다.

 

 

StringBuilder스레드 안전하지 않지만 빠른 속도를 제공합니다.

반면에 StringBuffer스레드 안전하지만 느린 속도를 제공합니다.

 

 

3. 비교 방법이 다른 이유 (내용 vs 주소)

또한, String 클래스와 StringBuilder/StringBuffer 클래스의 문자열 비교 방법도 다릅니다. 

String 클래스에서는 equals() 메소드를 사용하여 문자열을 비교합니다. 

equals() 메소드는 문자열 내용이 같은지를 비교합니다. 

반면에 == 연산자는 두 개의 객체가 같은 객체인지를 비교합니다.

 

즉, == 연산자는 두 개의 문자열이 같은지를 비교하는 것이 아니라, 두 개의 참조(=주소)가 같은지를 비교하는 것입니다.
아래는 String 클래스에서의 == 연산자 예시입니다.

String s1 = "Hello World";
String s2 = "Hello World";
System.out.println(s1 == s2); //true

위 코드에서 s1과 s2는 같은 문자열을 참조하고 있으므로 == 연산자는 true를 반환합니다.

4. StringBuilder 와 StringBuffer 의 차이

StringBuilder 클래스는 StringBuffer와 유사하게 문자열을 가변적으로 조작할 수 있도록 해줍니다. 

 

하지만 StringBuffer는 멀티스레드 환경에서 안전하도록 구현되어 있어서, 동기화 관련 오버헤드가 있습니다. 

그에 반해 StringBuilder는 단일 스레드 환경에서만 사용하도록 고안되어 있어서, 동기화 처리를 하지 않기 때문에 더 빠르게 문자열을 조작할 수 있습니다.

StringBuilder의 메서드는 StringBuffer와 유사하게 구성되어 있어서, 많은 부분이 동일합니다. 

하지만 동기화 처리가 빠진만큼 메서드 수행 시간이 더 빠르고, 더 효율적으로 동작합니다.

 

 

5. 응용!

그럼 내용을 다르게 수정했다가, 다시 원래대로 바꾸면, 참조 값이 다시 같아질까?

public class Test {
    public static void main(String[] args) {
        String s1 = "Hello World";
        String s2 = "Hello World";
		
        System.out.println(s1 == s2); //true
		
        s2 = s2 + "!";
        System.out.println(s1 == s2); //false
		
        s2 = "Hello World";
        System.out.println(s1 == s2); //true
    }
}

첫 번째 System.out.println(s1 == s2)는 s1과 s2가 모두 "Hello World" 문자열을 참조하고 있으므로 true를 출력합니다.

두 번째 System.out.println(s1 == s2)는 s2에 "!"를 추가한 후, s1과 비교하므로 false를 출력합니다. 이는 s2 + "!" 연산이 새로운 String 객체를 생성하고, 그 객체의 참조값을 s2가 가리키게 되기 때문입니다.

세 번째 System.out.println(s1 == s2)는 다시 s2를 "Hello World"로 초기화한 후, s1과 s2가 모두 같은 문자열을 참조하고 있으므로 true를 출력합니다.

 

+ 더 자세한 해설
Java의 String 클래스는 불변(immutable) 객체입니다. 

이는 생성된 String 객체가 변경 불가능하다는 것을 의미합니다. 

즉, 한 번 생성된 String 객체는 그 값을 변경할 수 없습니다.

이러한 불변성은 Java의 메모리 모델에서 매우 중요합니다. 

Java는 객체를 참조하는 변수가 있을 때, 해당 객체에 대한 참조 값을 변수에 저장합니다. 

불변 객체는 생성된 이후에 값이 변경될 수 없기 때문에, 이들의 값은 항상 일정합니다. 

따라서, 불변 객체에 대한 참조를 갖는 변수는 해당 객체가 가리키는 값을 변경할 수 없습니다. 

이러한 특성은 Java의 스레드 안정성(thread-safety)을 보장하는 데에도 도움을 줍니다.

하지만 이러한 불변성 때문에, String 객체를 수정하려고 하면 기존 객체를 변경하는 대신 새로운 객체를 생성합니다. 

예를 들어, String 객체에 대해 문자열 결합 연산자(+)를 사용하면, 기존 객체를 변경하는 대신, 두 개의 String 객체를 연결한 새로운 String 객체를 생성합니다. 

이 때문에 String을 연결하거나 수정하는 작업이 빈번하게 일어날 때, 메모리 소비가 높아질 수 있습니다.

그리고 불변성으로 인해 String 객체가 많은 수로 생성될 수 있다는 단점도 있습니다. 예를 들어, 문자열을 많이 연결하는 작업을 수행할 경우 새로운 String 객체가 생성될 수 있기 때문에 메모리 사용량이 늘어날 수 있습니다. 이러한 경우에는 StringBuilder나 StringBuffer 클래스를 사용하는 것이 더 효율적입니다. 이 클래스들은 가변(mutable) 객체로, 문자열을 연결할 때 기존 객체를 변경하는 대신에 내부적으로 저장공간을 조정하여 문자열을 추가할 수 있도록 해줍니다.

 

 

6. 총정리

그래서 언제 사용하는게 좋을까?!

String : 값이 자주 변하지 않을 때 (자주 변하면, 메모리 소비가 심함)

StringBuilder : 값이 변하고, 싱글스레드일때 (대신 빠름)

StringBuffer : 값이 변하고, 멀티스레드일때 (대신 느림)

 

 


이상으로, Java에서 문자열을 다루는 String, StringBuffer, StringBuilder 클래스에 대해 알아보았습니다. 

적절한 상황에서 각 클래스를 적절히 사용하면서, 보다 효율적으로 문자열을 다룰 수 있을 것입니다.

반응형
반응형

Array → List

원배열을 바꾸면, 복사한 배열도 변경하고 싶은지의 여부에 따라 선택

  • Arrays.asList(arr)
    얕은 복사(원 배열 공유=동기화) List<String> list = Arrays.asList(arr)
  • new ArrayList<>(Arrays.asList(arr))
    깊은복사(새로운 배열=비동기화) List<String> list = Arrays.asList(arr)
  • Collector.toList()
    Stream 사용 List<String> list = Stream.of(arr).collect(Collectors.toList());

List → Array

  • toArray() String arr[] = arrList.toArray(new String[Size])
    Object[]로 리턴이라, 타입 변환이 어려움
  • toArray(T[] t)
    위와 똑같지만 T 타입의 배열 명시 하지만 기본형만 가능(int, double, float은 불가능) [길이] : 길은 size를 직접 넣어도 되고, 0으로 넣으면 자동 조정
  • Stream
    int 등으로 저장할때 유용(Integer→intValue로 int형변환→toArray사용) list.stream().mapToInt(Integer::intValue).toArray();
반응형
반응형

Java에서 Array를 List로 바꾸는 방법은 많겠지만, 가장 간단한 방법들을 몇 개 소개해드리겠습니다.

1. Arrays 사용 

복사하려는 array의 type이 기본형이라면 가장 간편한 방법으로, 기본 함수 사용
(단,  Integer가 아닌 int형이라면 사용이 불가능)

2. Collection 사용

Collections를 사용하여 array를 복사하는 방법, 하지만 복사하려는 array의 type이 기본형이 아니라면 사용 불가능

3. for 사용

가장 기본적인 방법으로 for/stream등을 이용해서 array를 하나씩 읽어서 list에 새로 넣는 방법
번거로워 보이지만, 형변등 처리가 가능하므로 int형을 Integer로 바꿔서 처리할 수 있다.

      // 1 - Arrays 활용
      List<Integer> list = Arrays.asList(array);          

      // 2 - Collection 활용
      List<Integer> list = new ArrayList<Integer>();
      Collections.addAll(list, array);

      // 3 - for each 활용
      List<Integer> list = new ArrayList<Integer>();
      for(Integer text:array) {
         list.add(text);
      }

 

 

 

 

 

java array to list

how to convert array to list

반응형
반응형

기존에 많이 쓰고(보이던) Try catch finally 아닌
try catch with resources
자원해제 처리 방법에 대해 정리 해보았습니다

 

실제 사용

try ( FileOutputStream out =  new FileOutputStream(file);){

        out.write(content.getBytes(StandardCharsets.UTF_8));

    } catch (FileNotFoundException e) {

        e.printStackTrace();

 }

=>  finally와 그 안에 자원해제 처리를 위한 부가 작업 불필요

 

 

설명

Try 자원객체를 전달하면, try 코드블록이 끝남과 동시에 자동으로 자원을 종료해주는 기능 (JDK 7 부터 사용가능)

=> finally, catch 각각 종료 처리르 걸지 않아도 된다

=> try() 안에 복수의 자원을 전달 있다

, 이때 try 전달 가능한 자원은 autoCloseable 인터페이스의 구현체로 한정

 

장점

Try catch finally 사용시, if, try문을 중복해서 사용하는 번거로움(처리를 위한 처리)

= 비즈니스와 무관한 자원해제 처리를 위한 코드를 줄일 있다

 

사용법 (비교)

// 파일 생성 (try-catch-finally)
public void makeFile(String path, String title, String content){
    FileOutputStream out = null;
    try {
        File file = new File(path+"/"+title);

        if(!file.exists()) { file.createNewFile(); }

        out = new FileOutputStream(file);
        out.write(content.getBytes(StandardCharsets.UTF_8));

    }catch (Exception e){
        e.printStackTrace();
    }finally {
        if(out != null){
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

// 파일 생성 (try-catch-with-resource)
public void makeFile2(String path, String title, String content){

    File file = new File(path+"/"+title);

    try ( FileOutputStream out =  new FileOutputStream(file);){
        out.write(content.getBytes(StandardCharsets.UTF_8));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}
반응형
반응형

mybatis에서 mapper.xml(쿼리 작성해 놓는 xml파일)에서 파라미터를 쓸때,

2가지가 혼용되어 쓰이고 있어서 다시 한번 정리해봤습니다.

 

#{}

  • 파라미터가 String으로 들어와서(= 자동으로 '' 붙는다) 자동으로 '파라미터 '으로 적용
    • ( : where id = #{id} 이고 id 값이 1234, 쿼리에는 where id = '1234' 출력)
  • SQL Injection 예방

 

${}

  • 파라미터가 그대로 출력
  • 컬럼의 자료형에 맞춰 파라미터의 자료형이 변경
    • 사용자의 입력을 그대로 전달하는 경우에는 부적당
    • 테이블, 컬럼명을 파라미터로 전달할때 적당
  • SQL Injection 예방할 없음
반응형
반응형

Java에서 HashMap에 각각 a,b,c,d 순서대로 넣는다고 해서

a,b,c,d 순서대로 접근할 수는 없다

 

대신 순서대로 사용하려면 LinkedHashMap를 사용하자.

=> 순서가 있는 MAP

반응형

+ Recent posts