공변성 : 상속구조가 그대로 전달되는 성질
제네릭은 기본적으로 불공변 - 코드 유연성 떨어져서 => 와일드카드로 공정성/반공변성 지원
? extends T -> 공변성
? super T -> 반공변성
primtive타입 쓸 수 없는 이유 - 참조 타입이 아니어서 => wrapper로 사용
컴파일 과정 - 타입 소거(ex. List< String > -> List)
제네릭 타입 배열 선언 불가 - 배열은 공변성을 가지기 때문
컬렉션은 불공변성이어서 가능하지만 예외 발생
arraylist를 바라보는 관점 - collection vs generic
효율적 관리 / 타입에 구애받지 않는 만능 상자
타입 고정, 추가 삭제시 성능 문제, 초기 용량 설정과 메모리 낭비 / 타입 소거
원시 배열과 비교 - 최대 3배 정도 속도 차이 => 언제 어떤 걸 쓸지 정해두기
pecs 원칙(producer-extends, consumer-super)
for(int i=listStr.size()-1;i>=0;i--){
if(listStr.get(i).equals("world")){
listStr.remove(i);
}
}
Iterator<String> itr = listStr.iterator();
while(itr.hasNext()){
String str = itr.next();
if(str.equals("world")){
itr.remove();
}
}
살짝 느림
기본 툴
List<String> list = new ArrayList<>();
LocalDateTime start = LocalDateTime.now();
//
LocalDateTime end = LocalDateTime.now();
Duration d = Duration.between(start, end);
System.out.println(d.getNano());
arraylist vs linkedlist
add - 70000200 vs 200996000
for(int i=0;i<100_0000;i++){
list.add(new String("Hello"));
}
remove - 263296200 vs 25998400
List<String> list = new ArrayList<>();
// List<String> list = new LinkedList<>();
for(int i=0;i<100_0000;i++){
list.add(new String("Hello"));
}
LocalDateTime start = LocalDateTime.now();
//
for(int i=0;i<100_0000;i++){
list.remove("Hello");
}
LocalDateTime end = LocalDateTime.now();
Duration d = Duration.between(start, end);
System.out.println(d.getNano());
Collections.sort();
1. compareTo(){}
2. lambda
중복 허용 x, 순서 유지 x
Set<String> set = new HashSet<>();
set.add();
사용자 정의 클래스
Set<Node> set = new HashSet<>();
set.add(new Node(7,2));
set.add(new Node(3,4));
set.add(new Node(7,2));
set.add(new Node(5,3));
System.out.println(set);
7,2가 다르다고 판단함. heap의 주소값이 다르기 때문
=>
Node에 다음 값을 넣어야 7,2가 같다고 판단함
@Override
public int hashCode(){
return Objects.hash(x,y);
}
@Override
public boolean equals(Object obj){
if(this==obj) return true;
if(obj==null) return false;
if(getClass()!=obj.getClass()) return false;
Node other = (Node) obj;
return x == other.x && y ==other.y;
}
TreeSet에 넣으면 에러 발생 => 순서를 따질 수 있는 Comparable 구현
key, value로 구성되며 key는 중복 불가
Map<String, String> map = new HashMap<>();
map.put(key, value);
key가 같으면 새로운 value로 덮어씀
map.put("love","사랑");
System.out.println(map);
map.put("love","사랑하다");
System.out.println(map);
{love=사랑} -> {love=사랑하다}
map.get(key)
//key 순회
for(String key : map.keySet()){
System.out.print(key);
System.out.println(" : " + map.get(key));
}
//value 순회
for(String value : map.values()){
System.out.println(value);
}
functional programming : 단 하나의 추상메소드를 가지고 있는 interface; 추상메소드 => 단순처리
파라미터로 functional interface를 가지는 메소드
파라미터 객체를 이용해서 호출하는 메소드는 정해져 있음(결정적)
=> 람다식은 이미 정해진 한 개의 추상메소드를 구현하는 객체의 또 다른 표현
부수 효과가 없는 순수 함수를 1급 객체로 간주하여 파라미터나 반환값으로 사용할 수 있으며, 참조 투명성을 지킬 수 있다.
과거의 데이터는 일반적으로 RDB에 관리되는 데이터
현재의 데이터는 유의미성을 파악하기 전에 너무 많은 모습을 가지고 있음 => 클래스, 필드, 메소드를 만들어 유의미한 것을 찾는 거보다 훨씬 빨라야 하며 단순해야 함. 입력값+논리(역할, 기능)에만 의존
====
스트림 인터페이스
컬렉션, 배열, 숫자
파일로부터 스트림 얻기 - java.nio.file.Files
매핑 : 스트림의 요소를 다른 요소로 변환하는 중간 처리 기능
루핑 : 스트림에서 요소를 하나씩 반복해서 가져와 처리하는 것
동시성과 병렬성
String[] strArray = {"A","B","C"};
Stream<String> stream = Stream.of(strArray);
List<String> list = Arrays.asList("A","B","C");
Stream<String> stream2 = list.stream();
List<String> list2 = Arrays.asList("A","C","B","C","B");
Stream<String> stream21 = list.stream().distinct();//중복 제거
stream21.forEach(a -> System.out.println(a));
filter
입력 스트림
출력 스트림
바이트 스트림 : 그림, 멀티미디어, 문자 등 모든 종류 데이터 입출력, 느림
문자 스트림 : 문자만 입출력
io패키지, nio패키지
OutputStream / InputStream - int로 return
writer / reader
보조 스트림 - BuffereadInputStream/BuffereadOutputStream
File 클래스
public static void main(String[] args) throws Exception{
//File
String dirName = "C:"+File.separator+"myDir";
File file1 = new File(dirName);
if(file1.exists()){
System.out.println("exist");
}
else{
System.out.println("don't exist");
if(file1.mkdir()){
System.out.println("make");
}
}
// create file
File file2 = new File(dirName, "char.txt");
file2.createNewFile();
// delete file
if(file2.exists()){
System.out.println("exist file");
file2.delete();
}
}
serial
package ch18.serial;
import java.io.Serializable; // 추상 메소도 x
// 객체 직렬화 사용 - 객체 -> json / session -> file, 서버 초기화 -> session
public class MyClass implements Serializable { // marking
private static final long serialVersionUID = 1L;
int n;
transient int ssn; // 직렬화할때 값이 빠지게 됨 -> 0이나 null로 출력이 됨
String str;
}
====
package ch18.serial;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception{
// 직렬화
// MyClass mc = new MyClass();
// mc.n = 10;
// mc.ssn = 999;
// mc.str = "Hello";
// writeObject(mc);
MyClass mc = readObject();
System.out.println(mc.n);
System.out.println(mc.ssn);
System.out.println(mc.str);
}
static void writeObject(MyClass mc) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myClass.dat"));
oos.writeObject(mc);
oos.close();
}
static MyClass readObject() throws Exception{
MyClass mc = null;
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myClass.dat"));
mc = (MyClass) ois.readObject();
ois.close();
return mc;
}
}
serialVersionUID에 따라 실행이 되냐 안되냐 할 수 있음