java7에서 ThreadLocal을 초기화하는 코드이다.


참조 코드: https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html

import java.util.concurrent.atomic.AtomicInteger;


public class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);

// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =
new ThreadLocal<Integer>() {
@Override protected Integer initialValue() {
return nextId.getAndIncrement();
}
};

// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}


java8에서는 위의 코드를 



import java.util.concurrent.atomic.AtomicInteger;

public class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);

// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId = ThreadLocal.withInitial(()->new Integer(5));
// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}

또는


import java.util.concurrent.atomic.AtomicInteger;


public class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);

// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =
ThreadLocal.withInitial(() -> nextId.getAndIncrement());
// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}




간단 테스트 코드이다. 

public class ThreadLocalTest {
public static void main(String[] args) {
ThreadLocal<Integer> myThreadLocal = ThreadLocal.withInitial( ()-> new Integer(5));
System.out.println(myThreadLocal.get());
myThreadLocal.set(10);
System.out.println(myThreadLocal.get());
}
}



Posted by '김용환'
,




 List<Object>의 특정 값(id)만 List<String>으로 변환하고 싶을 때, 아래와 같이 stream과 Collectors.toCollection()를 호출하면 된다.



List<Person> persons = ...
List<String> ids = persons.stream().map(e -> e.
id).collect(Collectors.toCollection(ArrayList::new));

Posted by '김용환'
,


List를 고정 개수로 나누려면 Guava의 Lists.partition()을 쓰는 게 가장 좋다. stream을 쓰려면 따로 좀 복잡하게 만들어야 한다. 



List<Integer> list = ...;

List<List<Integer>>  subLists = Lists.partition(list, 10);



처음에는 stream의 partitionBy와 좀 혼동했었다. 특정 조건(predicate)에 의해서 쪼개려면 Collectors.paritioningBy를 사용한다.


import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

. @Test
public void test() {

Predicate<String> isFive = p -> p.length() == 5;

Map<Boolean, List<String>> list = Arrays.asList("samuel", "flynn", "merlin")
.stream()
.collect(Collectors.partitioningBy(isFive));

System.out.println(list);

}

결과


{false=[samuel, merlin], true=[flynn]}



groupingBy라는 있는데, 역시 Predicate대신 Function을 매개변수로 받는다. 결과는 동일하게 처리할 수 있다.
@Test
public void test() {

Function<String, Boolean> isFive = p -> p.length() == 5;

Map<Boolean, List<String>> list = Arrays.asList("samuel", "flynn", "merlin")
.stream()
.collect(Collectors.groupingBy(isFive));

System.out.println(list);
}

결과는 동일하다.




'java core' 카테고리의 다른 글

java8 ThreadLocal 초기화  (0) 2015.12.14
[java8] List<Object>를 List<String>으로 변환하기  (0) 2015.11.19
java8 소스 보기  (0) 2015.10.19
자바 null casting 주의 사항  (0) 2015.10.02
[java8] 배열을 java8 stream 처리하기  (0) 2015.09.24
Posted by '김용환'
,

java8 소스 보기

java core 2015. 10. 19. 18:48

컴파일 없이 단순히 java8 소스를 보려면 아래와 같이 하면 된다. 


$ hg clone http://hg.openjdk.java.net/jdk8/jdk8/


$ cd jdk8


$ bash get_source.sh


$ unset CLASSPATH


$ unset JAVA_HOME


$ bash configure



Posted by '김용환'
,




자바에서 null 관련된 테스트를 해보았다.



@Test

public void Test() {

Map numberAndCount = new HashMap<>();


int[] numbers = {1, 2, 3, 1};

for(int i : numbers){

Integer count = (Integer) numberAndCount.get(i);

numberAndCount.put(i, count++);

}

}



위의 코드는 numberAndCount 맵에서 count를 저장할 때, null인 count를 ++ 하면서 NPE가 발생한다.


자바에서 null 값인 객체를 클래스 캐스트하면 에러가 발생하지 않고, 실제 객체를 사용하는 시점에 NPE가 발생한다.



좀 더 간단한 형태로 만들면 다음과 같다. 


Object object = null;

String o = (String) object;

o.concat("1"); // npe 발생



그외 관련한 테스트 코드는 다음과 같다.



1. null == null, 컴파일/런타임 에러 발생하지 않는다.


if (null == null) {

System.out.println("null");

}


2. primitve type에 null 할당시 컴파일 에러가 발생한다.


int a = null;



3. primitive boxing 시 런타임시 에러가 발생한다.


Integer integer = null;

int i0 = (int) integer; // npe


int a = (Integer) null;  //npe




Posted by '김용환'
,




java8에서 String[]와 같은 배열을 바로 Stream을 쓸 수 있다.

Arrays.stream() 또는 Stream.of() 메소드를 사용하여 stream을 쓸 수 있다. 

@Test
public void arrayStream() {
String[] profiles = environment.getActiveProfiles();
String phaseString = Arrays.stream(profiles)
.filter(s -> s.equals("development"))
.findAny()
.orElse(null);

System.out.println(phaseString);

Object newPhaseString = Stream.of(profiles)
.filter(s -> s.equals("development"))
.findAny()
.orElse(null);

System.out.println(newPhaseString);


Posted by '김용환'
,


ArrayList의 구현이 Java8에서 바뀌면서 Collections.sort()  사용시 ConcurrentModificationException 발생하는 케이스가 있다고 소개한 적 있다.


http://knight76.tistory.com/entry/Java-8-AtomicReference%EC%97%90%EC%84%9C-%EB%A7%8C%EB%82%98%EB%8A%94-ConcurrentModificationException



최근에 Java8 25 이상 java8구현체에서 ArrayList의 subList()를 사용할 때에도 ConcurrentModificationException이 발생할 수 있다. (실제로 발생했다.)


관련 내용이 아래 Qiita 블로그에도 소개되어 있어서 해당 내용을 공유한다. 

http://qiita.com/kamatama_41/items/0b19564e2e72951edb8b



java8 25 이상 에서 subList로 뽑아낸 ArrayList를 소팅(Collections.sort)를 호출하면, Exception이 발생한다. 

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArrayListSortTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("bbb");
list.add("ccc");
list.add("aaa");

List<String> subList = list.subList(0, 2);
// [bbb, ccc]
System.out.println(subList);

Collections.sort(list);

// jdk1.8.0_11 -> [aaa, bbb]
// jdk1.8.0_25 -> ConcurrentModificationException
System.out.println(subList);

}
}

cme 예외가 발생하는 시점은 System.out.println(subList); 이다.


Exception in thread "main" java.util.ConcurrentModificationException

at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231)

at java.util.ArrayList$SubList.listIterator(ArrayList.java:1091)

at java.util.AbstractList.listIterator(AbstractList.java:299)

at java.util.ArrayList$SubList.iterator(ArrayList.java:1087)

at java.util.AbstractCollection.toString(AbstractCollection.java:454)

at java.lang.String.valueOf(String.java:2982)

at java.io.PrintStream.println(PrintStream.java:821)

at com.google.location.java8test.ArrayListSortTest.main(ArrayListSortTest.java:22)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:497)

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)


Process finished with exit code 1




Collections.sort()의 구현은 List.sort()로 호출하게 되어 있다.

public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}


저자가 사용하는 java8 40에서는 ArrayList.sort()는 다음과 같이 구현되어 있다. (참고로, modCount와 ExpectedModCount가 다르면 throw new ConcurrentModificationException이 발생하도록 되어 있다.)

@Override
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}

코드상으로는 Collections.sort() 호출 이후 System.out.println()에서 발생한다.

즉, subList 된 ArrayList를 Iterate 하면서 CME 예외가 발생했다.


ArrayList$SubList$ListIterator 구현에서 next() 메소드 호출시 checkForComodification() 메소드로 modCount를 비교하게 되어 있다. 이 때 개수가 안 맞으면 CME 예외가 발생한다. 참고로 remove(), before() 메소드가 호출될 때에도 동일하게 문제가 발생한다.

public Iterator<E> iterator() {
return listIterator();
}

public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
final int offset = this.offset;

return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = ArrayList.this.modCount;

public boolean hasNext() {
return cursor != SubList.this.size;
}

@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
}

public boolean hasPrevious() {
return cursor != 0;
}

@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[offset + (lastRet = i)];
}

@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = SubList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[offset + (i++)]);
}
// update once at end of iteration to reduce heap write traffic
lastRet = cursor = i;
checkForComodification();
}

public int nextIndex() {
return cursor;
}

public int previousIndex() {
return cursor - 1;
}

public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
ArrayList.this.set(offset + lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

public void add(E e) {
checkForComodification();

try {
int i = cursor;
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

final void checkForComodification() {
if (expectedModCount != ArrayList.this.modCount)
throw new ConcurrentModificationException();
}

};
}


참고로 CopyOnWriteArrayList에서도 동일한 CME 예외가 발생한다. 

이 문제를 해결하기 위해서는 subList() 가 아닌 새로운 ArrayList()로 만들어야 한다.

( 처음에는 subList() 구현 정책에 대해서는 조금 특이하다라는 느낌이 있었다....)

Lists.newArrayList(Iterables.limit(list, fetchsize))와 같이 사용해야 한다.


하지만, 뒤에 설명하겠지만, subList()로 만든 ArrayList는 임시로 써야지 계속 쓰면 안된다!!!! 즉 자바의 철학에 맞지 않다.


참고로, 위의 예제에서 ArrayList 대신 LinkedList를 사용하면 잘 동작하며 전혀 문제가 발생하지 않는다.

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class LinkedListSortTest {
public static void main(String[] args) {
List<String> list = new LinkedList<>();
list.add("bbb");
list.add("ccc");
list.add("aaa");

List<String> subList = list.subList(0, 2);
// [bbb, ccc]
System.out.println(subList);

Collections.sort(list);

// jdk1.8.0_11 -> [aaa, bbb]
// jdk1.8.0_25 -> ConcurrentModificationException
System.out.println(subList);

}
}

LinkedList에는 sort() 구현이 없어서 상..상위 클래스인 List 인터페이스의 default 메소드인 sort()를 사용한다. 아래 코드가 List.sort() 메소드인데, 아주 간단한 모델로 쓰고 있다. 따라서 CME 예외가 발생하지 않는다.


public interface List<E> extends Collection<E> {
...
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}


openjdk에 관련 글을 살펴보면 좋은 내용이 있다.  subList()는 단순히 임시적인 용도 써야지 그 이상으로 쓰면 쓰지 않도록 추천(??!!) 하고 있다. 


https://bugs.openjdk.java.net/browse/JDK-8079444

https://docs.oracle.com/javase/tutorial/collections/interfaces/list.html



Although the subList operation is extremely powerful, some care must be exercised when using it. The semantics of the List returned by subList become undefined if elements are added to or removed from the backing List in any way other than via the returned List. Thus, it's highly recommended that you use the List returned by subList only as a transient object — to perform one or a sequence of range operations on the backing List. The longer you use the subList instance, the greater the probability that you'll compromise it by modifying the backing List directly or through another subList object. Note that it is legal to modify a sublist of a sublist and to continue using the original sublist (though not concurrently).



http://docs.oracle.com/javase/8/docs/technotes/guides/collections/designfaq.html#a26


 The existence of [the List.subList] method means that people who write methods taking List on input do not have to write secondary forms taking an offset and a length (as they do for arrays). 


http://docs.oracle.com/javase/8/docs/api/java/util/List.html#subList-int-int-


The existence of [the List.subList] method means that people who write methods taking List on input do not have to write secondary forms taking an offset and a length (as they do for arrays). 




Posted by '김용환'
,




2의 제곱(Math.pow)의 값을 구하고, 지수 (Math.Exponent)를 얻고, Math.log를 이용한 지수 구하는 식을 테스트해 본다.


Math.log() 메소드를 이용해서 테스트 했다.

for (int i = 0; i < 35; i++) {
double p = Math.pow(2, i);
System.out.println(i + ":" + p + "\t" + Math.getExponent(p) + "\t" + (Math.log(p)/Math.log(2)));
}


결과는 다음과 같다.

0:1.0 0 0.0

1:2.0 1 1.0

2:4.0 2 2.0

3:8.0 3 3.0

4:16.0 4 4.0

5:32.0 5 5.0

6:64.0 6 6.0

7:128.0 7 7.0

8:256.0 8 8.0

9:512.0 9 9.0

10:1024.0 10 10.0

11:2048.0 11 11.0

12:4096.0 12 12.0

13:8192.0 13 13.0

14:16384.0 14 14.0

15:32768.0 15 15.0

16:65536.0 16 16.0

17:131072.0 17 17.0

18:262144.0 18 18.0

19:524288.0 19 19.0

20:1048576.0 20 20.0

21:2097152.0 21 21.0

22:4194304.0 22 22.0

23:8388608.0 23 23.0

24:1.6777216E7 24 24.0

25:3.3554432E7 25 25.0

26:6.7108864E7 26 26.0

27:1.34217728E8  27 27.0

28:2.68435456E8         28 28.0

29:5.36870912E8  29 29.000000000000004

30:1.073741824E9 30 30.0

31:2.147483648E9 31 31.000000000000004

32:4.294967296E9 32 32.0

33:8.589934592E9 33 33.0

34:1.7179869184E10 34 34.0



사실은 다음을 테스트하고 싶었다. 정말 값을 비교했을 때, 조금 작은 double 값의 차이가 나더라도 적당하게 동일한 값이 나온다고 알려줄까?? 사실은 다른 값이라고 명확하게 알린다. 따라서 Math.getExponent의 값을 쓰는 것이 낫다. 

Math.log를 이용하면 근접한 값이 나올 수는 있지만(예, 29, 31의 값), 값을 비교 할 때, 다른 값이라고 판단될 수 있다. 



for (int i = 0; i < 35; i++) {
double p = Math.pow(2, i);
double logP = Math.log(p) / Math.log(2);
double expP = Math.getExponent(p);

String isEqualToIandLogP = "X";
if (i == logP) {
isEqualToIandLogP = "O";
}

String isEqualToIandExpP = "X";
if (i == expP) {
isEqualToIandExpP = "O";
}
System.out.println(i + ":" + p + "\t" + expP + "\t" + logP + "\t" + isEqualToIandLogP + "\t" + isEqualToIandExpP);
}


0:1.0 0.0 0.0 O O

1:2.0 1.0 1.0 O O

2:4.0 2.0 2.0 O O

3:8.0 3.0 3.0 O O

4:16.0 4.0 4.0 O O

5:32.0 5.0 5.0 O O

6:64.0 6.0 6.0 O O

7:128.0 7.0 7.0 O O

8:256.0 8.0 8.0 O O

9:512.0 9.0 9.0 O O

10:1024.0 10.0  10.0 O O

11:2048.0 11.0  11.0 O O

12:4096.0 12.0  12.0  O O

13:8192.0 13.0  13.0 O O

14:16384.0 14.0  14.0 O O

15:32768.0 15.0  15.0 O O

16:65536.0 16.0  16.0 O O

17:131072.0 17.0  17.0 O O

18:262144.0 18.0  18.0 O O

19:524288.0 19.0  19.0 O O

20:1048576.0 20.0  20.0   O O

21:2097152.0 21.0  21.0   O O

22:4194304.0 22.0  22.0   O O

23:8388608.0 23.0  23.0   O O

24:1.6777216E7 24.0  24.0   O O

25:3.3554432E7 25.0  25.0   O O

26:6.7108864E7 26.0  26.0   O O

27:1.34217728E8 27.0  27.0   O O

28:2.68435456E8 28.0  28.0   O O

29:5.36870912E8 29.0  29.000000000000004   X O

30:1.073741824E9 30.0  30.0   O O

31:2.147483648E9 31.0  31.000000000000004   X O

32:4.294967296E9 32.0 32.0   O O

33:8.589934592E9 33.0  33.0   O O

34:1.7179869184E10 34.0  34.0   O O


Posted by '김용환'
,


실수 2 개 사이의 모든 수는 셀 수 없다.

그러나, 컴퓨터의 2개의 float (부동소수점) 값 사이에는 개수는 정해져 있다.


java의 Math 클래스의 nextup 메소드를 이용하면 그 다음 float 값을 찾을 수 있다. 

예제는 다음과 같다. 

public static void main (String [] args) {
int number = 0;
for (float x = 1.0f; x <= 2.0f; x = Math.nextUp(x)) {
number++;
}
System.out.println("number : " + number);
}

결과는  8388609 이다. 


인접하고 있는 float 숫자 사이에는 간격이 존재한다. 간격이 되는 값을 알아본다. 

float next = Math.nextAfter(1.0f, 2.0f);
System.out.println("next : " + next);

실행하면,  1.0000001을 확인할 수 있다. 

1.0f 부터 한 단계 큰 부동소수점 값은 1.0000001 이다.  0.0000001 값을 ulp (unit of least precision; 최종 자릿수)이라 한다.


ulp는 상대적인 값이다. float 값에 따라 0.0000002이 되기도 하고, 0.00006이 되기도 한다.

float next = Math.nextAfter(2.0f, 3.0f);
System.out.println("next : " + next + "\t" + Math.ulp(next)); // 결과 // next : 2.0000002 2.3841858E-7


float next = Math.nextAfter(1000.0f, 1100.0f);
System.out.println("next : " + next + "\t" + Math.ulp(next)); // 결과 // next : 1000.00006 6.1035156E-5


아래 코드를 실행해 본다.

int count = 0;
for (float x = 1.0f; x <= Float.MAX_VALUE ; x *= 2.0f) {
System.out.println (count++ + ": " + x + "\t\t"+ Math.getExponent(x) + "\t\t"+ Math.ulp (x));
}

결과

0: 1.0 0 1.1920929E-7

1: 2.0 1 2.3841858E-7

2: 4.0 2 4.7683716E-7

3: 8.0 3 9.536743E-7

4: 16.0 4 1.9073486E-6

5: 32.0 5 3.8146973E-6

6: 64.0 6 7.6293945E-6

7: 128.0 7 1.5258789E-5

8: 256.0 8 3.0517578E-5

9: 512.0 9 6.1035156E-5

10: 1024.0 10 1.2207031E-4

11: 2048.0 11 2.4414062E-4

12: 4096.0 12 4.8828125E-4

13: 8192.0 13 9.765625E-4

14: 16384.0 14 0.001953125

15: 32768.0 15 0.00390625

16: 65536.0 16 0.0078125

17: 131072.0 17 0.015625

18: 262144.0 18 0.03125

19: 524288.0 19 0.0625

20: 1048576.0 20 0.125

21: 2097152.0 21 0.25

22: 4194304.0 22 0.5

23: 8388608.0 23 1.0

24: 1.6777216E7 24 2.0

25: 3.3554432E7 25 4.0

26: 6.7108864E7 26 8.0

27: 1.34217728E8 27 16.0

28: 2.68435456E8 28 32.0

29: 5.3687091E8 29 64.0

30: 1.07374182E9 30 128.0

31: 2.14748365E9 31 256.0

32: 4.2949673E9 32 512.0

33: 8.5899346E9 33 1024.0

34: 1.71798692E10 34 2048.0

35: 3.4359738E10 35 4096.0

36: 6.8719477E10 36 8192.0

37: 1.37438953E11 37 16384.0

38: 2.74877907E11 38 32768.0

39: 5.4975581E11 39 65536.0

40: 1.09951163E12 40 131072.0

41: 2.19902326E12 41 262144.0

42: 4.3980465E12 42 524288.0

43: 8.796093E12 43 1048576.0

44: 1.7592186E13 44 2097152.0

45: 3.5184372E13 45 4194304.0

46: 7.0368744E13 46 8388608.0

47: 1.40737488E14 47 1.6777216E7

48: 2.81474977E14 48 3.3554432E7

49: 5.6294995E14 49 6.7108864E7

50: 1.12589991E15 50 1.34217728E8

51: 2.25179981E15 51 2.68435456E8

52: 4.5035996E15 52 5.3687091E8

53: 9.0071993E15 53 1.07374182E9

54: 1.80143985E16 54 2.14748365E9

55: 3.6028797E16 55 4.2949673E9

56: 7.2057594E16 56 8.5899346E9

57: 1.44115188E17 57 1.71798692E10

58: 2.88230376E17 58 3.4359738E10

59: 5.7646075E17 59 6.8719477E10

60: 1.1529215E18 60 1.37438953E11

61: 2.30584301E18 61 2.74877907E11

62: 4.611686E18 62 5.4975581E11

63: 9.223372E18 63 1.09951163E12

64: 1.8446744E19 64 2.19902326E12

65: 3.6893488E19 65 4.3980465E12

66: 7.3786976E19 66 8.796093E12

67: 1.4757395E20 67 1.7592186E13

68: 2.951479E20 68 3.5184372E13

69: 5.902958E20 69 7.0368744E13

70: 1.1805916E21 70 1.40737488E14

71: 2.3611832E21 71 2.81474977E14

72: 4.7223665E21 72 5.6294995E14

73: 9.444733E21 73 1.12589991E15

74: 1.8889466E22 74 2.25179981E15

75: 3.7778932E22 75 4.5035996E15

76: 7.5557864E22 76 9.0071993E15

77: 1.5111573E23 77 1.80143985E16

78: 3.0223145E23 78 3.6028797E16

79: 6.044629E23 79 7.2057594E16

80: 1.2089258E24 80 1.44115188E17

81: 2.4178516E24 81 2.88230376E17

82: 4.8357033E24 82 5.7646075E17

83: 9.6714065E24 83 1.1529215E18

84: 1.9342813E25 84 2.30584301E18

85: 3.8685626E25 85 4.611686E18

86: 7.7371252E25 86 9.223372E18

87: 1.54742505E26 87 1.8446744E19

88: 3.0948501E26 88 3.6893488E19

89: 6.1897002E26 89 7.3786976E19

90: 1.23794004E27 90 1.4757395E20

91: 2.4758801E27 91 2.951479E20

92: 4.9517602E27 92 5.902958E20

93: 9.9035203E27 93 1.1805916E21

94: 1.9807041E28 94 2.3611832E21

95: 3.9614081E28 95 4.7223665E21

96: 7.9228163E28 96 9.444733E21

97: 1.58456325E29 97 1.8889466E22

98: 3.1691265E29 98 3.7778932E22

99: 6.338253E29 99 7.5557864E22

100: 1.2676506E30 100 1.5111573E23

101: 2.5353012E30 101 3.0223145E23

102: 5.0706024E30 102 6.044629E23

103: 1.0141205E31 103 1.2089258E24

104: 2.028241E31 104 2.4178516E24

105: 4.056482E31 105 4.8357033E24

106: 8.112964E31 106 9.6714065E24

107: 1.6225928E32 107 1.9342813E25

108: 3.2451855E32 108 3.8685626E25

109: 6.490371E32 109 7.7371252E25

110: 1.2980742E33 110 1.54742505E26

111: 2.5961484E33 111 3.0948501E26

112: 5.192297E33 112 6.1897002E26

113: 1.0384594E34 113 1.23794004E27

114: 2.0769187E34 114 2.4758801E27

115: 4.1538375E34 115 4.9517602E27

116: 8.307675E34 116 9.9035203E27

117: 1.661535E35 117 1.9807041E28

118: 3.32307E35 118 3.9614081E28

119: 6.64614E35 119 7.9228163E28

120: 1.329228E36 120 1.58456325E29

121: 2.658456E36 121 3.1691265E29

122: 5.316912E36 122 6.338253E29

123: 1.0633824E37 123 1.2676506E30

124: 2.1267648E37 124 2.5353012E30

125: 4.2535296E37 125 5.0706024E30

126: 8.507059E37 126 1.0141205E31

127: 1.7014118E38 127 2.028241E31




float가 점점 커질 수록(exp 계산) 숫자 간격이 점점 커진다(ulp). 그래서 수치해석할 때, Math.ulp 메소드가 의미가 있을 수 있다. 따라서 float 형 (또는 double형)이 얼마나 큰 수가 될 수 있는지에 따라 신경을 써야할 수치해석이 필요한 것 같다.





Posted by '김용환'
,



Java8에서 Stream.forEach Slf4j의 Logger 메소드를 사용하면 에러가 발생한다.
해당 이유는 Slf4j의 Logger.info() 의 매개변수가 모두 String이기 때문이다.

(참고로 Commons의 Log.info()의 매개변수는 모두 Object이기 때문에 Streams.forEach안에서 사용하면 문제가 발생하지 않는다.)


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ConvertObjectTest {
private Logger logger = LoggerFactory.getLogger(ConvertObjectTest.class);

@Test
public void convertObjectListWithFunctionTest() {

OneMember samuel = new OneMember(1, "Samuel");
OneMember daisy = new OneMember(2, "Daisy");
OneMember matt = new OneMember(3, "Matt");

List<String> persons = Stream.of(samuel, daisy, matt)
.map(OnePerson::new)
.sorted(comparing(OnePerson::getId))
.collect(toList())
.forEach(Logger::info); } }



에러가 발생하지 않게 하기 위해서는 객체를 String으로 변환시키고 peek을 실행시키는 방법을 사용한다.




import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ConvertObjectTest {
private Logger logger = LoggerFactory.getLogger(ConvertObjectTest.class);

@Test
public void convertObjectListWithFunctionTest() {

OneMember samuel = new OneMember(1, "Samuel");
OneMember daisy = new OneMember(2, "Daisy");
OneMember matt = new OneMember(3, "Matt");

List<String> persons = Stream.of(samuel, daisy, matt)
.map(OnePerson::new)
.sorted(comparing(OnePerson::getId))
.map(OnePerson::toString)
.peek(logger::error)
.collect(toList());

}


Posted by '김용환'
,