RandomStringUtils.randomNumeric(int count)
- count 만큼 랜덤한 숫자를 생성
- count 만큼 랜덤한 숫자를 생성
public static boolean isNotEmpty(Collection<?> coll)
Null returns false.
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}]
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}]
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}]
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) |
자바에서 맵에서 특정 키(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}
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}
단어의 빈도 수를 체크하는 프로그램을 만들 때
어떤 단어가 몇 번 나왔는지 체크할때 유용하게 사용할 수있다.
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}
위에 결과를 compute로 바꾸면 에러(NullPointerException)가 발생한다.
CANADA가 없기 때문이다. CANADA가 없다면 결과는 동일하다.
값이 없을 때 널을 피하기 위하여 디폴트를 지정할 수 있다.
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