숙제
- Stream.collect 함수에 대해 정리, Stream.Collectors(https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html)에 있는 각종 컬렉터에 대해 정리
- Stream을 만들 수 있는 여러가지 방법에 대해 정리
- 동시성과 병렬성의 구분
- 교착상태(deadlock)이 발생하기 위한 조건과 방지 방법
- 스핀락(spinlock)의 정의와 사용 이유 정리
- 6. 자바 OutputStream과 Writer의 차이점 / 자바 InputStream과 Reader의 차이점
7. java.util.Scanner 사용법
1. Stream.collect 함수에 대해 정리
+Stream.Collectors(https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html)에 있는 각종 컬렉터에 대해 정리
수집
· 요소들을 필터링 또는 매핑한 후 요소들을 수집하는 최종 처리 메소드
· 필요한 요소만 컬렉션으로 담거나, 요소들을 그룹핑한 후 집계(리덕션)할 수 있음
· 스트림에서 제공하는 수집 메소드: collect()
필터링한 요소 수집
· Stream의 collect(Collector<T,A,R> collector) 메소드는 필터링 또는 매핑된 요소들을 새로운 컬렉션에 수집하여 리턴함
리턴 타입 | 메소드(매개 변수) | 인터페이스 |
R | collect(Collector<T,A,R> collector) | Stream |
· 매개값인 Collector(수집기)는 어떤 요소를 어떤 컬렉션에 수집할 것인지 결정
· Collector의 타입 파타미터 의미: T - 요소, A - 누적기(accumulator) , R - 요소가 저장될 컬렉션
- T 요소를 A 누적기가 R에 저장한다는 의미
· Collector의 구현 객체는 Collectors 클래스의 정적 메소드를 이용해 얻을 수 있음
리턴 타입 | Collectors의 정적 메소드 | 설명 |
Collector<T,?,List<T>> | toList() | T를 List에 저장 |
Collector<T,?,Set<T>> | toSet() | T를 Set에 저장 |
Collector<T,?,Collection<T>> | toCollectio( Supplier<Collection<T>>) |
T를 Supplier가 제공한 Collection에 저장 |
Collector<T,?,Map<K,U>> | toMap( Function<T,K> keyMapper, Function<T,U> valueMapper) |
T를 K와 U로 매핑해서 K를 키로 U를 Map에 저장 |
Collector<T,?, ConcurrentMap<K,U>> |
toConcurrentMap( Function<T,K> keyMapper, Function<T,U> valueMapper) |
T를 K와 U로 매핑해서 K를 키로 U를 ConcurrentMap에 저장 |
· 리턴 타입의 Collector의 A가 ?로 되어 있는 이유: Collector가 R(컬렉션)에 T(요소)에를 저장하는 방법을 알고 있어 A(누적기)가 필요 없기 때문이다.
· ConcurrentMap은 스레드에 안전, Map은 스레드에 안전 x
- 멀티 스레드 환경에서 ConcurrentMap 이용 권장
▶ 예시 - 야채 색상별로 서로 다른 자료구조에 저장하기
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CollectDemo {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",Vegetable.Color.GREEN),
new Vegetable("tomato", Vegetable.Color.RED),
new Vegetable("redPepper",Vegetable.Color.RED),
new Vegetable("cabbage",Vegetable.Color.GREEN),
new Vegetable("eggplant",Vegetable.Color.PURPLE)
);
// 초록색 야채를 List 자료구조에 저장
Stream<Vegetable> greenVegetableStream = vegetables.stream()
.filter(s->s.getColor()==Vegetable.Color.GREEN);
Collector<Vegetable, ?, List<Vegetable>> collector = Collectors.toList();
List <Vegetable> greenVegetables = greenVegetableStream.collect(collector);
// 빨간색 야채를 HashSet 자료구조에 저장
Stream<Vegetable> redVegetableStream = vegetables.stream()
.filter(s->s.getColor()==Vegetable.Color.RED);
Supplier<HashSet<Vegetable>> supplier = HashSet::new;
Collector<Vegetable, ?, HashSet<Vegetable>> collector2 = Collectors.toCollection(supplier);
Set <Vegetable> redVegetables = redVegetableStream.collect(collector2);
greenVegetables.stream().forEach(vegetable-> System.out.println(vegetable.getName()));
System.out.println();
redVegetables.stream().forEach(vegetable-> System.out.println(vegetable.getName()));
}
public static class Vegetable{
public enum Color {GREEN, RED,PURPLE}
String name;
Color color;
Vegetable(String name, Color color){
this.name = name;
this.color = color;
}
String getName(){
return name;
}
Color getColor(){
return color;
}
}
}
위 코드에서 변수를 생량하여 다음과 같이 간단하게 작성할 수 있다.
public class CollectDemo {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",Vegetable.Color.GREEN),
new Vegetable("tomato", Vegetable.Color.RED),
new Vegetable("redPepper",Vegetable.Color.RED),
new Vegetable("cabbage",Vegetable.Color.GREEN),
new Vegetable("eggplant",Vegetable.Color.PURPLE)
);
// 초록색 야채를 List 자료구조에 저장
List <Vegetable> greenVegetables = vegetables.stream()
.filter(s->s.getColor()==Vegetable.Color.GREEN)
.collect(Collectors.toList());
// 빨간색 야채를 HashSet 자료구조에 저장
Set<Vegetable> redVegetables = vegetables.stream()
.filter(s->s.getColor()==Vegetable.Color.RED)
.collect(Collectors.toCollection(HashSet::new));
greenVegetables.stream().forEach(vegetable-> System.out.println(vegetable.getName()));
System.out.println();
redVegetables.stream().forEach(vegetable-> System.out.println(vegetable.getName()));
}
public static class Vegetable{
public enum Color {GREEN, RED,PURPLE}
String name;
Color color;
Vegetable(String name, Color color){
this.name = name;
this.color = color;
}
String getName(){
return name;
}
Color getColor(){
return color;
}
}
}
사용자 정의 컨테이너에 수집
· List, Set, Map과 같은 컬렉션이 아니라 사용자 정의 컨테이너 객체에 수집하는 방법
· 스트림에서는 필터링, 매핑해서 사용자 정의 컨테이너 객체에 수집할 수 있는 collect() 메소드를 추가적으로 제공
인터페이스 | 리턴 타입 | 메소드(매개 변수) |
Stream | R | Collect(Supplier<R>, BiConsumer<R,? super T>, BiConsumer<R,R>) |
IntStream | R | Collect(Supplier<R>, ObjIntConsumer<R>, BiConsumer<R,R>) |
LongStream | R | Collect(Supplier<R>, ObjLongConsumer<R>, BiConsumer<R,R>) |
DoubleStream | R | Collect(Supplier<R>, ObjDoubleConsumer<R>, BiConsumer<R,R>) |
· Supplier: 수집될 컨테이너 객체(R)을 생성하는 역할
- 순차 처리(싱글 스레드) 스트림에서는 단 한 번 Supplier가 실행되고 하나의 컨테이너 객체를 생성
- 병렬 처리(멀티 스레드) 스트림에서는 여러 번 Supplier가 실행되고 스레드별로 여러 개의 컨테이너 객체를 생성
· 두 번째 Consumer: 컨테이너 객체(R)에 요소(T)를 수집하는 역할
- 스트림에서 요소를 컨테이너에 수집할 때마다 실행
· 세 번째 Consumer: 컨테이너 객체(R)를 결합하는 역할
- 병렬 처리 스트림에서 호출되어 스레드별로 생성된 컨테이너 객체를 결합해서 단 하나의 최종 컨테이너 객체를 완성
- 순차 처리 스트림에서는 호출되지 않음
· 리턴 타입 R: 요소들이 최종 수집된 컨테이너 객체
- 순차 처리 스트림에서 리턴 객체: 첫 번째 Supllier가 생성한 객체
- 병렬 처리 스트림에서 리턴 객: 최종 결합된 컨테이너 객체
▶ 예시 - GreenVegetable 사용자 컨테이너에 데이터 수집
public class GreenVegetable {
private List<Vegetable> list; //요소를 저장할 컬렉션
public GreenVegetable(){
list = new ArrayList<Vegetable>();
System.out.println("[" + Thread.currentThread().getName() + "] GreenVegetable()");
}
// 매개값으로 받은 Vegetable을 list 필드에 수집
public void accumulate(Vegetable vegetable){ //요소를 수집하는 메소드
list.add(vegetable);
System.out.println("[" + Thread.currentThread().getName() + "] accumulate()");
}
// 병렬 처리 스트림을 사용할 때 다른 GreenVegetable과 결합할 목적으로 실행
public void combine(GreenVegetable other){
list.addAll(other.getList());
System.out.println("[" + Thread.currentThread().getName() + "] combine()");
}
public List<Vegetable> getList(){ //요소가 저장된 컬렉션 리턴
return list;
}
}
public class UserDefinedContainerCollectDemo {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",Vegetable.Color.GREEN),
new Vegetable("tomato", Vegetable.Color.RED),
new Vegetable("redPepper",Vegetable.Color.RED),
new Vegetable("cabbage",Vegetable.Color.GREEN),
new Vegetable("eggplant",Vegetable.Color.PURPLE)
);
Stream<Vegetable> greenVegetableStream = vegetables.stream()
.filter(s->s.getColor() == Vegetable.Color.GREEN);
Supplier<GreenVegetable> supplier = () -> new GreenVegetable(); //GreenVegetable을 공급하는 supplier 얻기
BiConsumer<GreenVegetable, Vegetable> accumulator = (ms, s) -> ms.accumulate(s); //accumulator로 Vegetable을 수집하는 BiConsumer 얻기
//두 개의 Greentable을 매개값으로 받아 combin() 메소드로 결합하는 BiConsumer 얻기. 싱글 스레드에서는 사용 x.
BiConsumer<GreenVegetable, GreenVegetable> combiner = (ms1, ms2)->ms1.combine(ms2);
//GreenVegetable 수집
GreenVegetable greenVegetable = greenVegetableStream.collect(supplier, accumulator, combiner);
//수집한 GreenVegetable 출력
greenVegetable.getList().stream()
.forEach(s->System.out.println(s.getName()));
}
}
위 람다식을 메소드 참조로 변경하면 다음과 같이 간단하게 작성 가능
public class UserDefinedContainerCollectDemo {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",Vegetable.Color.GREEN),
new Vegetable("tomato", Vegetable.Color.RED),
new Vegetable("redPepper",Vegetable.Color.RED),
new Vegetable("cabbage",Vegetable.Color.GREEN),
new Vegetable("eggplant",Vegetable.Color.PURPLE)
);
GreenVegetable greenVegetable = vegetables.stream()
.filter(s->s.getColor() == Vegetable.Color.GREEN)
.collect(GreenVegetable :: new, GreenVegetable:: accumulate, GreenVegetable :: combine);
greenVegetable.getList().stream()
.forEach(s->System.out.println(s.getName()));
}
}
요소를 그룹핑해서 수집
· collect() 메소드는 요소를 수집하는 기능 이외에 컬렉션 요소들을 그룹핑해서 Map 객체를 생성하는 기능도 제공
· 사용법: collect()를 호출할 때 Collectors의 groupingBy() 또는 groupingByConcurrent()가 리턴하는 Collector를 매개값으로 대입
▶ 예시 - 야채를 색상과 크기로 각각 그룹핑
public class Vegetable{
public enum Color {GREEN, RED,PURPLE}
public enum Size {SMALL, MEDIUM, BIG}
private String name;
private Color color;
private Size size;
Vegetable(String name, Color color, Size size){
this.name = name;
this.color = color;
this.size = size;
}
String getName(){
return name;
}
Color getColor(){
return color;
}
Size getSize(){
return size;
}
}
public class GroupingDemo {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",Vegetable.Color.GREEN, Vegetable.Size.BIG),
new Vegetable("tomato", Vegetable.Color.RED, Vegetable.Size.MEDIUM),
new Vegetable("redPepper",Vegetable.Color.RED, Vegetable.Size.SMALL),
new Vegetable("cabbage",Vegetable.Color.GREEN, Vegetable.Size.BIG),
new Vegetable("eggplant",Vegetable.Color.PURPLE, Vegetable.Size.MEDIUM)
);
Function<Vegetable, Vegetable.Color> classifier = Vegetable :: getColor; //Vegetable을 Vegetable.Color로 매핑하는 Function 얻기
//Vegetable.Color가 키, 그룹핑된 List<Vegetable>가 값인 Map을 생성하는 Collector를 얻기
Collector<Vegetable, ?, Map<Vegetable.Color, List<Vegetable>>> collector = Collectors.groupingBy(classifier);
Map<Vegetable.Color, List<Vegetable>> mapByColor = vegetables.stream().collect(collector); //Stream의 collect() 메소드로 Vegetable를 Vegetable.Color별로 그룹핑해서 Map을 얻음
System.out.print("초록색 야채:");
mapByColor.get(Vegetable.Color.GREEN).forEach(s-> System.out.print(s.getName() + " "));
System.out.println();
System.out.print("빨간색 야채:");
mapByColor.get(Vegetable.Color.RED).forEach(s-> System.out.print(s.getName() + " "));
System.out.println();
System.out.print("보라색 야채:");
mapByColor.get(Vegetable.Color.PURPLE).forEach(s-> System.out.print(s.getName() + " "));
System.out.println();
Function<Vegetable, Vegetable.Size> classifier2 = Vegetable :: getSize;
Function<Vegetable, String> mapper = Vegetable::getName;
Collector<String, ?, List<String>> collector2 = Collectors.toList();
Collector<Vegetable, ?, List<String>> collector3 = Collectors.mapping(mapper,collector2);
Collector<Vegetable, ?, Map<Vegetable.Size, List<String>>> collector4 = Collectors.groupingBy(classifier2, collector3);
//collect()의 매개값으로 groupingBy(Function<T, K> classifier, Collector<T, A, D> collector) 사용
Map<Vegetable.Size, List<String>> mapBySize = vegetables.stream().collect(collector4);
System.out.print("큰 야채:");
mapBySize.get(Vegetable.Size.BIG).forEach(s-> System.out.print(s + " "));
System.out.println();
System.out.print("중간 야채:");
mapBySize.get(Vegetable.Size.MEDIUM).forEach(s-> System.out.print(s + " "));
System.out.println();
System.out.print("작은 야채:");
mapBySize.get(Vegetable.Size.SMALL).forEach(s-> System.out.print(s + " "));
System.out.println();
}
}
위 코드의 변수를 생략하면 다음과 같이 간단하게 작성 가능
public class GroupingDemo {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",Vegetable.Color.GREEN, Vegetable.Size.BIG),
new Vegetable("tomato", Vegetable.Color.RED, Vegetable.Size.MEDIUM),
new Vegetable("redPepper",Vegetable.Color.RED, Vegetable.Size.SMALL),
new Vegetable("cabbage",Vegetable.Color.GREEN, Vegetable.Size.BIG),
new Vegetable("eggplant",Vegetable.Color.PURPLE, Vegetable.Size.MEDIUM)
);
Map<Vegetable.Color, List<Vegetable>> mapByColor = vegetables.stream()
.collect(Collectors.groupingBy(Vegetable :: getColor));
System.out.print("초록색 야채:");
mapByColor.get(Vegetable.Color.GREEN).forEach(s-> System.out.print(s.getName() + " "));
System.out.println();
System.out.print("빨간색 야채:");
mapByColor.get(Vegetable.Color.RED).forEach(s-> System.out.print(s.getName() + " "));
System.out.println();
System.out.print("보라색 야채:");
mapByColor.get(Vegetable.Color.PURPLE).forEach(s-> System.out.print(s.getName() + " "));
System.out.println();
Map<Vegetable.Size, List<String>> mapBySize = vegetables.stream()
.collect(
Collectors.groupingBy(
Vegetable::getSize,
Collectors.mapping(Vegetable::getName, Collectors.toList()))
);
System.out.print("큰 야채:");
mapBySize.get(Vegetable.Size.BIG).forEach(s-> System.out.print(s + " "));
System.out.println();
System.out.print("중간 야채:");
mapBySize.get(Vegetable.Size.MEDIUM).forEach(s-> System.out.print(s + " "));
System.out.println();
System.out.print("작은 야채:");
mapBySize.get(Vegetable.Size.SMALL).forEach(s-> System.out.print(s + " "));
System.out.println();
}
}
그룹핑 후 매핑 및 집계
· Collectors.groupingBy() 메소드는 그룹핑 후 매핑이나 집계(평균, 카운팅, 연결, 최대, 최소, 합계)를 할 수 있도록 두 번째 매개값으로 Collector를 가질 수 있음
· Collectors는 매핑과 집계를 위한 Collector를 리턴하는 다양한 메소드를 제공(아래)
리턴 타입 | 메소드(매개 변수) | 설명 |
Collector<T, ?, R> | mapping(Function<T, U> mapper, Collector<U, A, R> collector> | T를 U로 매핑한 후, U를 R에 수집 |
Collector<T, ?, Double> | averagingDouble(ToDoubleFunction<T> mapper) | T를 Double로 매핑한 후, Double의 평균값을 산출 |
Collector<T, ?, Long> | counting() | T의 카운팅 수를 산출 |
Collector<CharSequence, ?, String> | joining(CharSequence delimiter) | CharSequence를 구분자로 연결한 String을 산출 |
Collector<T, ?, Optional<T>> | maxBy(Comparator<T> comparator) | Comparator를 이용해서 최대 T를 산출 |
Collector<T, ?, Optional<T>> | minBy(Comparator<T> comparator) | Comparator를 이용해서 최소 T를 산출 |
Collector<T, ?, Integer> | summingInt(ToIntFunction) summingLong(ToLongFunction) summingDouble(ToDoubleFunction) |
Int, Long, Double 타입의 합계 산출 |
▶ 예시 - 야채의 색상별 무게의 평균과 이름 얻기
public class Vegetable{
public enum Color {GREEN, RED,PURPLE}
private String name;
private double kg;
private Color color;
Vegetable(String name, double kg, Color color){
this.name = name;
this.kg = kg;
this.color = color;
}
String getName(){
return name;
}
Color getColor(){
return color;
}
double getKg() { return kg; }
}
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import java.util.stream.Collector;
import java.util.stream.Collectors;
public class GroupingAndReductionExample {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",0.3,Vegetable.Color.GREEN),
new Vegetable("tomato",0.2, Vegetable.Color.RED),
new Vegetable("redPepper",0.1,Vegetable.Color.RED),
new Vegetable("cabbage",2.0,Vegetable.Color.GREEN),
new Vegetable("eggplant",0.5,Vegetable.Color.PURPLE)
);
//1. 그룹핑 절차 그대로 보여주기
//야채의 색상별 평균 무게를 저장하는 Map 얻기
Function<Vegetable, Vegetable.Color> classifier = Vegetable :: getColor;
ToDoubleFunction<Vegetable> mapper = Vegetable::getKg;
Collector<Vegetable, ?, Double> collector1 = Collectors.averagingDouble(mapper);
Collector<Vegetable, ?, Map<Vegetable.Color, Double>> collector2 = Collectors.groupingBy(classifier, collector1);
Map<Vegetable.Color, Double> mapByColor = vegetables.stream().collect(collector2);
System.out.println("초록색 야채 전체 평균:" + mapByColor.get(Vegetable.Color.GREEN));
System.out.println("빨간색 야채 전체 평균:" + mapByColor.get(Vegetable.Color.RED));
System.out.println("보라색 야채 전체 평균:" + mapByColor.get(Vegetable.Color.PURPLE));
//2. 변수 생략으로 간단하게 표현하기
//야채의 색상을 쉽표로 구분한 이름을 저장하는 Map 얻기
Map<Vegetable.Color, String> mapByName = vegetables.stream()
.collect(
Collectors.groupingBy(
Vegetable :: getColor,
Collectors.mapping(Vegetable :: getName, Collectors.joining(","))
)
);
System.out.println("초록색 야채 전체 이름:" + mapByName.get(Vegetable.Color.GREEN));
System.out.println("빨간색 야채 전체 이름:" + mapByName.get(Vegetable.Color.RED));
System.out.println("보라색 야채 전체 이름:" + mapByName.get(Vegetable.Color.PURPLE));
}
}
위 코드의 변수를 생략하면 다음과 같이 간단하게 작성 가능
public class GroupingAndReductionExample {
public static void main(String[] args){
List<Vegetable> vegetables = Arrays.asList(
new Vegetable("broccoli",0.3,Vegetable.Color.GREEN),
new Vegetable("tomato",0.2, Vegetable.Color.RED),
new Vegetable("redPepper",0.1,Vegetable.Color.RED),
new Vegetable("cabbage",2.0,Vegetable.Color.GREEN),
new Vegetable("eggplant",0.5,Vegetable.Color.PURPLE)
);
//야채의 색상별 평균 무게를 저장하는 Map 얻기
Map<Vegetable.Color, Double> mapByColor = vegetables.stream()
.collect(
Collectors.groupingBy(
Vegetable :: getColor,
Collectors.averagingDouble(Vegetable :: getKg)
)
);
System.out.println("초록색 야채 전체 평균:" + mapByColor.get(Vegetable.Color.GREEN));
System.out.println("빨간색 야채 전체 평균:" + mapByColor.get(Vegetable.Color.RED));
System.out.println("보라색 야채 전체 평균:" + mapByColor.get(Vegetable.Color.PURPLE));
//야채의 색상을 쉽표로 구분한 이름을 저장하는 Map 얻기
Map<Vegetable.Color, String> mapByName = vegetables.stream()
.collect(
Collectors.groupingBy(
Vegetable :: getColor,
Collectors.mapping(Vegetable :: getName, Collectors.joining(","))
)
);
System.out.println("초록색 야채 전체 이름:" + mapByName.get(Vegetable.Color.GREEN));
System.out.println("빨간색 야채 전체 이름:" + mapByName.get(Vegetable.Color.RED));
System.out.println("보라색 야채 전체 이름:" + mapByName.get(Vegetable.Color.PURPLE));
}
}
2. Stream을 만들 수 있는 여러가지 방법에 대해 정리
스트림 구현 객체를 얻기 위한 메소드
리턴 타입 | 메소드(매개 변수) | 소스 |
Stream<T> | java.util.Collection.stream() java.util.Collection.parallelStream() |
컬렉션 |
Stream<T> IntStream LongStream DoubleStream |
Arrays.stream(T[]), Stream.of(T[]) Arrays.stream(int []), IntStream.of(int[]) Arrays.stream(long[]), LongStream.of(long[]) Arrays.stream(double[]), DoubleStream.of(double[]) |
배열 |
IntStream | IntStream.range(int, int) IntStream.rangeClosed(int, int) |
int 범위 |
LongStream | LongStream.range(long, long) LongStream.rangeClose(long, long) |
long 범위 |
Stream<Path> | Files.find(Path, int, BiPredicate, FileVisitOption) Files.list(Path) |
디렉토리 |
Stream<String> | Files.line(Path, charset) BufferedReader.lines() |
파일 |
DoubleStream IntStream LongStream |
Random.doubles() Random.ints() Random.longs() |
랜덤 수 |
컬렉션에서 스트림 얻기
List<String> list = Arrays.asList("tester1","tester2","tester3");
Stream<String> stream = list.stream();
stream.forEach(name -> System.out.println(name));
배열에서 스트림 얻기
String[] vegetables = {"broccoli","tomato","cabbage"};
Stream<String> stream = Arrays.stream(vegetables);
stream.forEach(s-> System.out.println(s))
숫자 범위에서 스트림 얻기
IntStream intStream = IntStream.rangeClosed(1,100);
intStream.forEach(i -> System.out.println(i)); //1부터 100까지 출력
파일에서 스트림 얻기
· Files와 BufferedReader의 lines() 메소드를 이용하여 문자 파일의 내용을 스트림을 통해 행 단위로 읽고 콘솔에 출력
Path path = Paths.get("/Users/ted.sc/Desktop/java8.txt");
Stream<String> stream;
//1. Filses.lines() 메소드 이용
stream = Files.lines(path, Charset.defaultCharset()); //운영체제의 기본 문자셋
stream.forEach(System.out::println); //메소드 참조, (s->System.out.println(s))과 동일
//2. BufferedReader의 lines() 메소드 이용
File file = path.toFile();
FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
stream = br.lines();
stream.forEach(System.out::println);
디렉토리에서 스트림 얻기
Path path = Paths.get("/Users/ted.sc/Desktop");
Stream<Path> stream = Files.list(path); //서브 디렉토리, 파일 목록을 스트림에 입력
stream.forEach(System.out::println);
3. 동시성과 병렬성의 구분
· 동시성(Concurrency): 두 개 이상의 작업이 겹치는 시간에 시작, 실행, 완료 되는 것이다. 단, 여러 작업이 반드시 동일한 순간에 실행되는 것은 아니다. ex) 단일 코어 시분할 방식
· 병렬성(Parallelism): 두 개 이상의 스레드가 동시에 실행되는 것이다.
출처
https://docs.oracle.com/cd/E19455-01/806-5257/6je9h032b/index.html
4. 교착상태(deadlock)가 발생하기 위한 조건과 방지 방법
https://scshim.tistory.com/382
5. 스핀락(spinlock)의 정의와 사용 이유 정리
https://scshim.tistory.com/manage/posts/
6. 자바 OutputStream과 Writer의 차이점 / 자바 InputStream과 Reader의 차이점
OutputStream
· 바이트 기반 입력 스트림의 최상위 클래스(추상 클래스)
· byte 자료형으로 데이터를 출력
· 모든 바이트 기반 출력 스트림은 이 클래스를 상속(FileOutputStream, BufferedOutputStream, DataOutputStream)
· 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 읽을 수 있음
Writer
· 문자 기반 입력 스트림의 최상위 클래스(추상 클래스)
· char 자료형으로 데이터를 출력
· 모든 문자 기반 출력 스트림은 이 클래스를 상속(FileWriter, BufferedWriter, PrintWriter, OutputStreamWriter)
· 문자 데이터를 읽는 데 특화
InputStream
· 바이트 기반 입력 스트림의 최상위 클래스(추상 클래스)
· byte 자료형으로 데이터를 입력
· 모든 바이트 기반 출력 스트림은 이 클래스를 상속(FileInputStream, BufferedInputStream, DataInputStream)
· 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 읽을 수 있음
Reader
· 문자 기반 입력 스트림의 최상위 클래스(추상 클래스)
· char 자료형으로 데이터를 입력
· 모든 문자 기반 입력 스트림은 이 클래스를 상속(FileReader. BufferedReader, InputStreamReader)
· 문자 데이터를 읽는 데 특화
7. java.util.Scanner 사용법
'스터디 > F-lab' 카테고리의 다른 글
[F-lab] 7주차 정리 - 웹 프로그래밍 기초와 JSP (0) | 2021.10.07 |
---|---|
[F-lab] 3주차 정리_자바 (0) | 2021.08.31 |
[F-lab] 2주차 정리_자바 (0) | 2021.08.24 |
댓글