월간 보관물: 2014 4월

java -jar 실행시 외부 jar 파일에 대한 classpath 가 동작하지 않는다.

내가 만든 java 프로그램을 실행 가능한 jar 로 묶는다. 이때 외부 라이브러리를 사용하기 위해서 classpath 에 외부 라이브러리 경로를 적어주고 다음과 같이 실행을 한다.

java -jar myprogram.jar -cp (또는 classpath) "./lib/externaljar.jar" 

위 처럼 실행을 하면 externaljar.jar 에 정의된 클래스를 찾을 수 없다는 NoClassDefFoundError 와 같은 오류를 만나게 될것이다.

java -jar 형태로 실행하게 되면 외부 jar 경로를 명시한 classpath 는 무시된다. 해결 방법으로는 내가 만든 프로그램까지 모두 classpath 에 명시한 뒤 실행할 class 를 직접 명시하는 방법이다.

java -cp "./myprogram.jar:./lib/externaljar.jar" com.wordpress.referto.MainClass 

guava Multimaps.newMultimap() 을 이용하여 원하는 multimap 만들기

guava 는 google 에서 제공하는 다양한 자료구조와 유틸리티들을 모아둔 라이브러리이다. 최근 map 자료구조를 사용하면서 하나의 key 에 value 가 리스트로 붙는 자료구조가 필요하게 되었다. 그냥 자바 코드로 생각하면 다음과 같은 모양이다.

Map<String, List<String>> multimap = new HashMap<String, List<String>>();
multimap.put( "key", new ArrayList<String>() );
multimap.get( "key" ).add("value1");
multimap.get( "key" ).add("value2");

guava 의 Multimap 자료 구조를 이용하면 다음과 같이 단순화 할 수 있다.

Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("key", "value1");
multimap.put("key", "value2");

List 와 Map 에도 다양한 implementation 이 있듯이 guava 에서도 multimap 에 대한 다양한 implementation 이 존재한다.

하지만 모든 기대를 충족할 수는 없으니 좀 더 custom 된 multimap 이 필요하게 되었다. 바로 key 는 알파벳순으로 정렬이 되지만 value 는 삽입된 순서대로 정렬이 되는 구조의 multimap 이다. 이러한 multimap 을 위해서 각 특성을 가진 collection 을 인자로 받아서 multimap 을 선언할 수 있도록 Multimaps.newMultimap() 이라는 인터페이스가 존재한다. key 는 정렬을 할 수 있도록 TreeMap 을 사용하였고 value 부분은 삽입 순서만 지키면 되어서 ArrayList 를 사용하였다.

   Multimap<String, String> options = Multimaps.newMultimap(
                new TreeMap<String, Collection<String>>(), new Supplier<List<String>>() {
            @Override
            public List<String> get() {
                return Lists.newArrayList();
            }
        });

        options.put("z", "d");
        options.put("z", "a");
        options.put("b", "c");
        options.put("b", "e");
        options.put("b", "d");
        options.put("a", "c");
        options.put("a", "b");

        final Iterator<String> iter = options.keySet().iterator();

        while ( iter.hasNext() ){
            String s = iter.next();
            System.out.println(s + " / " + options.get(s) );
        }

java string 의 공백 제거, 12288 문자 제거하기

Java 에서 문자열의 앞, 뒤, 그리고 중간 공백을 모두 제거하기 위해서 다음과 같은 코드를 사용한적이 있다.

String s = s.trim().replaceAll(" ", "");

이런식으로 대부분의 공백은 제거 되지만 일부 언어의 공백이 제거되지 않고 남아 있는 경우가 있었는데 그 character 값을 찍어보니 12288값이 나왔다.
정확한 정의는 찾지 못했지만 IDEOGRAPHIC SPACE 라고 불리는 문자이고 한국,중국,일본어 등에서 나오는 공백 문자인것 같다.

이를 제거하기 위해서는 위와 같은 방법이 아닌 아래와 같은 방법을 사용한다.

String s = s.replaceAll("\\p{Z}", "");

좀 더 자세한 답변은 stackoverflow 참고.