RandomStringUtils.randomNumeric(int count)

- count 만큼 랜덤한 숫자를 생성

isNotEmpty

public static boolean isNotEmpty(Collection<?> coll)
Null-safe check if the specified collection is not empty.

Null returns false.

Parameters:
coll - the collection to check, may be null

Returns:

true if non-null and non-empty

  1. 기본정렬
  2. 역순정렬
  3. null포함(nullLast)
  4. null포함(nullFirst)

1.기본 정렬

List<Member> list = List.of(Member.of(10), Member.of(20), Member.of(30));

List<Member> result = list.stream()
    .sorted(Comparator.comparing(Member::getAge))
    .collect(Collectors.toList());

System.out.println(result);

결과

[Member{age=10}, Member{age=20}, Member{age=30}]

2.역순 정렬

List<Member> list = List.of(Member.of(10), Member.of(20), Member.of(30));

List<Member> result = list.stream()
     .sorted(Comparator.comparing(Member::getAge, Comparator.reverseOrder()))
     .collect(Collectors.toList());

System.out.println(result);

결과

[Member{age=30}, Member{age=20}, Member{age=10}]

3.null 포함 nullLast

List<Member> list = List.of(Member.of(10), Member.of(null), Member.of(30));

List<Member> result = list.stream()
    .sorted(Comparator.comparing(Member::getAge, Comparator.nullsLast(Comparator.naturalOrder())))
    .collect(Collectors.toList());

System.out.println(result);

결과

[Member{age=10}, Member{age=30}, Member{age=null}]

4.null 포함 nullFirst

List<Member> list = List.of(Member.of(10), Member.of(null), Member.of(30));

List<Member> result = list.stream()
    .sorted(Comparator.comparing(Member::getAge, Comparator.nullsFirst(Comparator.naturalOrder())))
    .collect(Collectors.toList());

System.out.println(result);

결과

[Member{age=null}, Member{age=10}, Member{age=30}]

예제 Member class

class Member{

    Integer age;

    public Member(Integer age){
        this.age = age;
    }

    public static Member of(Integer age){
        return new Member(age);
    }

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Member{" +
                "age=" + age +
                '}';
    }
}
public class SomeService {

	private String action(String param){
    		return param + "test";
    	}

}

Test 작성시 private 메서드의 경우 직접 접근을 할 수가 없다.
invoke를 통해서 접근 가능하다. 

@Test
public void 문자열_테스트(){
	
    SomeService someService = new SomeService();
    
    Method testMethod = SomeService.class.getDeclaredMethod("action", String.class);
    testMethod.setAccessible(true);
    testMethod.invoke(someService, "Hello");
    
}

 

parallel 를 이용하면 병렬처리를 할 수 있다 하지만 기본적으로 서버의 CPU 코어 수에 따라 종속적이라고 한다.
커스텀하게 이용하기 위해서는 ForkJoinPool 을 이용하면 된다. 

List<String> list = Collections.synchronizedList(new ArrayList<>());

ForkJoinPool forkJoinPool = new ForkJoinPool(3);
forkJoinPool.submit(() -> 
	return IntStream.range(1, 100000)
	.parallel()
	.mapToObj(i -> list.add(new Integer(i).toString()))
    .collect(Collectors.toList())
).get();

System.out.println(list);
System.out.println(list.size());

첫번째 줄에 Collections.synchronizedList(new ArrayList<>())사용한 이유는 담는 리스트에 여러 쓰레드가 접근할 경우 동시에 접근하기 때문에 갯수가 다르거나 ArrayIndexOutOfBoundsException 가 발생한다.
단순한 예제로 속도에는 별 차이가 없었다.   병렬처리는 주의깊게 사용해야함을 느껴진다. 

Junit4 

import static org.assertj.core.api.Assertions.assertThatThrownBy;
...
assertThatThrownBy(()->Integer.parseInt("One")).isInstanceOf(NumberFormatException.class);

 

Junit5

import org.junit.jupiter.api.Assertions;
...
Assertions.assertThrows(NumberFormatException.class, () -> {
      Integer.parseInt("One");
    });

웹 개발을 하다보면 리스트에서 항목 중 자식 리스트를 갖는 것을 표현하고 싶을 때 유용하게 쓸 수 있다. 

 

Course League
1코스 1부
1코스 2부
2코스 1부
2코스 2부

데이터 베이스에서 4행이 리턴된다.  1코스 = {1부, 2부} , 2코스 = {1부, 2부}

Course League
1코스 [{부=1부, 코스=1코스}, {부=2부, 코스=1코스}]
2코스 [{부=1부, 코스=2코스}, {부=2부, 코스=2코스}]

화면에서는 위와 같이 2행으로 보여주려면 어떻게 해야 할까? 

Java Stream GroupBy을 이용하여 변경할 수 있다.

 

기본 데이터 

List<Map<String, String>> list = new ArrayList<>();

Map<String, String> course1_1 = new HashMap<>();
course1_1.put("코스", "1코스");
course1_1.put("부", "1부");
Map<String, String> course2_2 = new HashMap<>();
course2_2.put("코스", "2코스");
course2_2.put("부", "2부");

Map<String, String> course2_1 = new HashMap<>();
course2_1.put("코스", "2코스");
course2_1.put("부", "1부");

Map<String, String> course1_2 = new HashMap<>();
course1_2.put("코스", "1코스");
course1_2.put("부", "2부");

list.add(course1_1);
list.add(course1_2);
list.add(course2_1);
list.add(course2_2);

Stream 에 group by  를 활용

List<Map> newList = list.stream()
  .collect(Collectors.groupingBy((map) -> map.get("코스")))
  .entrySet().stream()
  .sorted((a, b) -> b.getKey().compareTo(a.getKey()))
  .map(entry -> {
    Map map = new HashMap();
    map.put("course", entry.getKey());
    map.put("league", entry.getValue());
    return map;
  })
  .collect(Collectors.toList());

결과는 

courseAndData = {league=[{부=1부, 코스=2코스}, {부=2부, 코스=2코스}], course=2코스}
courseAndData = {league=[{부=1부, 코스=1코스}, {부=2부, 코스=1코스}], course=1코스}
computeIfAbsent​(K key, Function<? super K,​? extends V> mappingFunction)
putIfAbsent​(K key, V value)
computeIfPresent​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction)
compute​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction)

computeIfAbsent 와 putIfAbsent 

자바에서 맵에서 특정 키(Key)들에 항목(Value)을 넣어주고 싶은 경우가 있다. 

 

Key Value
1 KOREA
2 USA
4 JAPAN
? ?

추가되는 키가 없을 경우 함수를 호출해서 항목을 넣어줄 수 있다.

 

만약 키 값이 4 = CHINA , 5 = CANADA 를 리턴하는 함수 선언

private String getCountry(String key){
	System.out.println("@@@@@ : " + key);
	return key.equals("4") ? "CHINA" : "CANADA";
}

맵에는 1,2,3 에 대한 값만 있고, 키 리스트는 1,2,3,4,5 일 경우 

computeIfAbsent를 이용하여 4,5에 값을 넣을 수 있다.

List<String> keyList = new ArrayList<>();
keyList.add("1");
keyList.add("2");
keyList.add("3");
keyList.add("4");
keyList.add("5");

Map<String, String> map = new HashMap<>();
map.put("1", "KOREA");
map.put("2", "USA");
map.put("3", "JAPAN");

for(String s : keyList){
	map.computeIfAbsent( s, (key) -> getCountry(key) );
}

System.out.println("map = " + map);

결과는 putIfAbsent 도 동일한 결과를 보여준다

map = {1=KOREA, 2=USA, 3=JAPAN, 4=CHINA, 5=CANADA}

computeIfAbsent 와 putIfAbsent 차이

putIfAbsent는 키(Key)가 있음에도 함수를 호출함 (*단 항목을 변경하지 않음)

 

computeIfAbsent 의 결과 출력

@@@@@ : 4
@@@@@ : 5
map = {1=KOREA, 2=USA, 3=JAPAN, 4=CHINA, 5=CANADA}

putIfAbsent 의 결과 출력

@@@@@ : 1
@@@@@ : 2
@@@@@ : 3
@@@@@ : 4
@@@@@ : 5
map = {1=KOREA, 2=USA, 3=JAPAN, 4=CHINA, 5=CANADA}

computeIfPresent 와 compute

단어의 빈도 수를 체크하는 프로그램을 만들 때

어떤 단어가 몇 번 나왔는지 체크할때 유용하게 사용할 수있다.

 

text에 단어가 몇 번 나왔는지 맵에 저장, 일단 초기값은 0 이다.

String text = "KOREA KOREA USA USA USA CANADA JAPAN ";

Map<String, Integer> wordMap = new HashMap<>();

wordMap.put("KOREA", 0);
wordMap.put("USA", 0);
wordMap.put("CHINA", 0);
wordMap.put("JAPAN", 0);

 

computeIfPresent 을 이용하여 빈도 수를 계산한다.

for(String word : text.split(" ")){
	wordMap.computeIfPresent(word, (String key, Integer value) ->  ++value);
}

System.out.println("wordMap = " + wordMap);

 

결과는... 

wordMap = {USA=3, CHINA=0, JAPAN=1, KOREA=2}

computeIfPresent 와 compute 차이

위에 결과를 compute로 바꾸면 에러(NullPointerException)가 발생한다. 

CANADA가 없기 때문이다. CANADA가 없다면 결과는 동일하다. 

 

그리고 ... getOrDefault

값이 없을 때 널을 피하기 위하여 디폴트를 지정할 수 있다. 

Map<String, String> map = new HashMap<>();
map.put("1", "KOREA");
map.put("2", "USA");

System.out.println("map = " + map.getOrDefault("3", "FRANCE"));
System.out.println("map = " + map.get("3"));

결과는...

map = FRANCE
map = null

+ Recent posts