익명객체
- 구현 클래스가 매번 달라지거나, 한 번만 사용되는 경우 구현 클래스를 생성하지 않고 익명 클래스(이름이 없는 클래스)로 선언할 수 있다.
package anonymous.basic;
interface Car {
public void run(); // 추상 메서드
}
class Sonata implements Car {
@Override
public void run() {
System.out.println("소나타가 달립니다.");
}
}
public class Garage {
// public Car car = new Sonata(); 일반적인 인터페이스 구현 객체 사용법
public Car car = new Car() {
public void run() {
System.out.println("익명객체가 달립니다.");
}
};
public Garage() {
car.run();
}
}
package anonymous.basic;
public class MainClass {
public static void main(String[] args) {
Car s1 = new Sonata();
s1.run();
Car s2 = new Sonata();
s2.run();
// Garage g = new Garage();
Car tesla = new Car() {
@Override
public void run() {
System.out.println("테슬라가 달립니다.");
}
};
tesla.run();
new Car() {
@Override
public void run() {
System.out.println("포르쉐는 쌩쌩 달립니다.");
}
}.run();
}
}
package anonymous.basic2;
public interface RemoteController {
void turnOn();
void turnOff();
void volumeUp();
void volumeDown();
}
package anonymous.basic2;
public class Tv implements RemoteController{
private int volume;
@Override
public void turnOn() {
System.out.println("Tv를 켭니다.");
}
@Override
public void turnOff() {
System.out.println("Tv를 끕니다.");
}
@Override
public void volumeUp() {
volume++;
System.out.println("Tv의 볼륨: " + volume);
}
@Override
public void volumeDown() {
volume--;
System.out.println("Tv의 볼륨: " + volume);
}
}
package anonymous.basic2;
public class Radio {
private int sound;
private RemoteController remote;
public Radio() {
remote = new RemoteController() {
@Override
public void volumeUp() {
sound++;
System.out.println("라디오의 볼륨: " + sound);
}
@Override
public void volumeDown() {
sound--;
System.out.println("라디오의 볼륨: " + sound);
}
@Override
public void turnOn() {
System.out.println("라디오를 켭니다.");
}
@Override
public void turnOff() {
System.out.println("라디오를 끕니다.");
}
};
}
public RemoteController getRemote() {
return remote;
}
public void setRemote(RemoteController remote) {
this.remote = remote;
}
}
package anonymous.basic2;
public class MainClass {
public static void main(String[] args) {
Tv tv = new Tv();
tv.turnOn();
tv.turnOff();
tv.volumeUp();
tv.volumeDown();
//////////////////////////////////////
Radio radio = new Radio();
radio.getRemote().turnOn();
radio.getRemote().turnOff();
radio.getRemote().volumeUp();
radio.getRemote().volumeDown();
}
}
람다식(Lambda Expression)
- 함수적 프로그래밍
- Y = f(x); 형태의 함수로 구성된 프로그래밍 기법
- 함수를 매개 값으로 전달하고 결과를 받는 코드로 구성
함수적 프로그래밍이 객체 지향 프로그래밍 보다는 효율적인 경우
- 대용량 데이터의 처리시
- 이벤트 지향 프로그램시
Java 8부터 함수적 프로그래밍을 지원한다.
- 람다식(Lambda Expression)를 제공한다.
- 익명 함수를 생성하기 위한 식
- (매개변수, 매개변수) -> { 실행문 }
람다식의 장점
- 코드가 간결해 진다.
- 컬렉션 요소 처리가 쉬워진다.
람다식의 기본 사용
- 자바의 람다식은 함수적 인터페이스의 익명 구현 객체를 대신한다.
- 람다식(Lambda Expression)은 코드블럭(code block)을 메소드에 넣을 때 사용하는 기술이다.
package lambda.basic;
//함수적 인터페이스 -> 구현해야 하는 추상 메서드가 1개인 인터페이스
public interface Say01 {
void talking();
}
package lambda.basic;
public interface Say02 {
String talking();
}
package lambda.basic;
public interface Say03 {
String talking(String greet);
}
package lambda.basic;
public interface Say04 {
String talking(String word, int i);
}
package lambda.basic;
public class Person {
public void greet(Say01 say) {
say.talking();
}
public void greet(Say02 say) {
say.talking();
}
public void greet(Say03 say) {
say.talking("안녕하세요");
}
public String greet(Say04 say) {
String result = say.talking("반갑습니다.", 3);
return result;
}
}
package lambda.basic;
interface Calculator {
int add(int n1, int n2);
}
public class MainClass {
public static void main(String[] args) {
Person p = new Person();
p.greet(new Say01() {
@Override
public void talking() {
System.out.println("안녕하세요.");
}
});
p.greet(new Say02() {
@Override
public String talking() {
System.out.println("Hello");
return "Hello";
}
});
p.greet(new Say03() {
@Override
public String talking(String greet) {
System.out.println(greet);
return greet;
}
});
String say04test = p.greet(new Say04() {
@Override
public String talking(String word, int i) {
String result = "";
for (int j = 1; j <= i; j++) {
result += word;
}
return result;
}
});
System.out.println("Say04 기본 메서드 호출: " + say04test);
System.out.println("------------------------------------");
p.greet(() -> {
System.out.println("안녕하세요.");
});
p.greet((greet) -> {
System.out.println();
return greet;
});
String str = p.greet((word, i) -> {
String result = "";
for (int j = 1; j <= i; j++) {
result += word;
}
return result;
});
System.out.println(str);
System.out.println("------------------------------------");
// 계산기 인터페이스와 람다식
Calculator sharp = new Calculator() {
@Override
public int add(int n1, int n2) {
System.out.println("샤프 계산기의 덧셈");
return n1 + n2;
}
};
System.out.println(sharp.add(10, 15));
Calculator casio = (x, y) -> {
System.out.println("카시오 계산기의 덧셈");
return x + y;
};
System.out.println(casio.add(100, 200));
// 만약 오버라이딩 하는 추상메서드에 작성할 코드가 한 줄이면 괄호 생략이 가능하다.
Calculator xiaomi = (x, y) -> x + y;
System.out.println(xiaomi.add(30, 50));
}
}
람다식을 적용하기 위한 스트림
반복자 스트림이란?
- Java 8부터 추가된 컬렉션의 저장 요소를 하나씩 참조하도록 도와주는 반복자이다.
- 람다식으로 처리할 수 있도록 해주는 반복자로 파일 입출력 stream과는 다른 개념이다.
스트림의 특징
- Iterator와 비슷한 역할을 하는 반복자로 대부분 메서드는 함수적 인터페이스 타입이라 속도면에서 빠르다.
package lambda.stream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class MainClass01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("홍길동");
list.add("김철수");
list.add("박영희");
list.add("김뽀삐");
list.add("최또띠");
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
System.out.println("---------------------------------");
/*
Stream<String> stream = list.stream();
stream.forEach(new Consumer<String>() {
@Override
public void accept(String t) {
System.out.println(t);
}
});
*/
list.stream().forEach((s) -> System.out.println(s));
}
}
package lambda.stream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class MainClass02 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
list.add((int) (Math.random() * 100) + 1);
}
System.out.println(list);
System.out.println("------------------------------");
// distinct(): 중복제거
list.stream()
.distinct()
.forEach((num) -> System.out.print(num + " "));
System.out.println("\n------------------------------");
// filter(): 걸러내는 기능
Stream<Integer> s1 = list.stream()
.filter((num) -> num % 2 == 0);
// 작성한 조건식의 결과가 true면 리턴
s1.forEach((num) -> System.out.print(num + " "));
System.out.println("\n------------------------------");
// sorted(): 정렬
list.stream()
.sorted()
.forEach((num) -> System.out.print(num + " "));
System.out.println("\n------------------------------");
// map(): 메서드 안에 정의된 새로운 stream으로 반환
Stream<String> s2 = list.stream().map((num) -> {
return num % 2 == 0 ? "짝수" : "홀수";
});
s2.forEach((str) -> System.out.print(str + ", "));
System.out.println("\n------------------------------");
// 50보다 크면 값을 반환, 아니면 0을 반환
list.stream()
.map((t) -> t > 50 ? t : 0)
.forEach((t) -> System.out.print(t + " "));
System.out.println("\n------------------------------");
// 50보다 크면 원본을 반환, 아니면 0을 반환, 0을 제거 후 출력
list.stream()
.map((num) -> num > 50 ? num : 0)
.filter((i) -> i != 0)
.forEach((j) -> System.out.print(j + " "));
}
}
Lambda Stream Quiz
1. BufferedReader를 사용해서 csv파일을 읽어들인다.
2. ,(콤마)를 기준으로 잡아서 분할 한 뒤 Data객체에 한 줄 단위로 저장
3. List<Data>에 추가한다.
4. 람다식을 이용해서 지역: 서울, 월: 짝수 의 분양가격이 4000 이상의 객체만 뽑아서 새로운 list를 생성. (filter)
stream.collect(Collectors.toList()) -> 스트림 객체의 요소를 모아서 새로운 리스트 생성.
5. 새롭게 만들어진 리스트 내부의 내용을 모두 출력
package lambda.stream; public class Data { private String region; private String size; private String year; private String month; private String price; public Data() { } public Data(String region, String size, String year, String month, String price) { super(); this.region = region; this.size = size; this.year = year; this.month = month; this.price = price; } public String getRegion() { return region; } public void setRegion(String region) { this.region = region; } public String getSize() { return size; } public void setSize(String size) { this.size = size; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public String getMonth() { return month; } public void setMonth(String month) { this.month = month; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } @Override public String toString() { return "지역명: " + region + ", 규모구분: " + size + ", 연도: " + year + "년" + " " + month + "월" + ", 분양가격: " + price + "만원"; } }
package lambda.stream; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class QuizMain { public static void main(String[] args) { // FileReader fr = null; BufferedReader br = null; // Data 객체들을 모아놓는 리스트 List<Data> list = new ArrayList<>(); FileInputStream fis = null; InputStreamReader is = null; // 인코딩을 지정해서 가져올 수 있는 클래스 try { fis = new FileInputStream("C:\\java\\주택도시보증공사_전국 평균 분양가격(2020년 2월).csv"); is = new InputStreamReader(fis, "EUC-KR"); br = new BufferedReader(is); String str; while((str = br.readLine()) != null) { String[] arr = str.split(","); // System.out.println(Arrays.toString(arr)); String region = arr[0]; String size = arr[1]; String year = arr[2]; String month = arr[3]; String price; try { // 공백, - 제거 arr[4] = arr[4].replace("-", "").replace(" ", ""); if (arr[4].equals("")) { price = "0"; // 없는 값이라면 0을 저장 } else { price = arr[4]; } } catch (Exception e) { price = "0"; } Data data = new Data(region, size, year, month, price); list.add(data); } /* List<Data> newList = list.stream().filter((data) -> data.getRegion().equals("서울")) .filter((data) -> Integer.parseInt(data.getMonth()) % 2 == 0) .filter((data) -> Integer.parseInt(data.getPrice()) >= 4000) .collect(Collectors.toList()); */ List<Data> newList = list.stream().filter((data) -> data.getRegion().equals("서울") && Integer.parseInt(data.getMonth()) % 2 == 0 && Integer.parseInt(data.getPrice()) >= 4000) .collect(Collectors.toList()); newList.stream().forEach((data) -> System.out.println(data)); } catch (Exception e) { e.printStackTrace(); } finally { try { br.close(); is.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
정규표현식(Regular Expression)
- 문자열이 정해진 패턴으로 구성되어 있는지 검증해야 할 때 사용한다. (이메일, 전화번호 등)
- 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어로 지정한 패턴과 일치하는 문자열을 검증할 수 있다.
Pattern 클래스
- java.util 패키지의 Pattern 클래스의 matcher(), matchers() 메서드를 정규표현식 검증에 이용한다.
- static 메서드
- compile(패턴)
- 정규표현엔진(정규식)을 만들어 낸다.
- matcher(검증 데이터)
- 데이터를 비교해서 Matcher 클래스로 반환한다.
- matchers(패턴, 검증 데이터)
- 패턴으로 비교하여 boolean 형으로 반환한다.
- compile(패턴)
Matcher 클래스
- 패턴을 이용하여 대상 문자열을 검색할 때 사용하는 클래스다.
- find()
- 해당 정규표현을 찾는다.
- start()
- 해당 정규표현의 시작 인덱스를 반환한다.
- group()
- 해당 정규표현의 값을 반환한다.
- end()
- 해당 정규표현의 끝 인덱스를 반환한다.
- find()
package regex.pattern;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexEx01 {
public static void main(String[] args) {
String info = "30세/서울시 마포구/02-123-4567/010-2345-6789/kkk@naver.com";
/*
* 전화번호 형식
* \\d: 숫자 형식인지 파악
* \\d{3} : 숫자 3개를 찾음
* \\d{3, 4}: 숫자가 3 이상 4 이하를 찾음
*/
String pattern = "\\d{2,3}-\\d{3,4}-\\d{4}";
// 비교/검증이 가능한 정규표현식을 만들어 내는 메서드
Pattern p = Pattern.compile(pattern);
// 데이터를 비교해서 Matcher 클래스로 반환
Matcher m = p.matcher(info);
/*
if(m.find()) {
System.out.println("찾은 인덱스: " + m.start());
System.out.println("끝 인덱스: " + m.end());
System.out.println("찾은 값: " + m.group());
}
*/
while(m.find()) {
System.out.println("찾은 인덱스: " + m.start());
System.out.println("끝 인덱스: " + m.end());
System.out.println("찾은 값: " + m.group());
}
/*
* 이메일 형식
* \\w: 영문자와 숫자를 찾는다.
* \\w+: 영문자와 숫자 여러개
*/
String pattern2 = "\\w+@\\w+.\\w+";
Matcher m2 = Pattern.compile(pattern2).matcher(info);
while(m2.find()) {
System.out.println("찾은 인덱스: " + m2.start());
System.out.println("끝 인덱스: " + m2.end());
System.out.println("찾은 값: " + m2.group());
}
}
}
package regex.pattern;
import java.util.regex.Pattern;
public class RegexEx02 {
public static void main(String[] args) {
//[]: 해당 위치의 한 글자에 어떤 문자들이 올 수 있는지 정의
System.out.println(Pattern.matches("s[lh]eep", "sleep"));
System.out.println(Pattern.matches("s[lh]eep", "sweep"));
/*
* # [] 안에 정의할 수 있는 것
* 1. [abc]: a, b, c 중 하나만 허용
* 2. [^abc]: a, b, c를 제외한 모두를 허용
* 3. [a-z]: a부터 z까지 허용
* [a-zA-Z가-힣]: 영문 소문자, 대문자, 한글을 허용
* 4. [0-9]: 숫자만 허용
* 5. &&: 교집합 (좌항과 우항 패턴을 모두 만족하는 문자)
*/
System.out.println(Pattern.matches("s[^1-9]eep", "s0eep"));
System.out.println(Pattern.matches("s[a-zA-Z]eep", "sLeep"));
System.out.println(Pattern.matches("s[a-dm-z]eep", "sleep"));
System.out.println(Pattern.matches("s[a-d&&c-f]eep", "sceep"));
/*
* # 해당 패턴이 적용될 문자의 개수를 정의하는 법 (공백은 허용하지 않는다.)
* 1. Ex{n}: 앞에 있는 패턴이 n글자 일치해야 한다.
* 2. Ex{n,m}: 최소 n글자 최대 m글자가 일치해야 한다.
* 3. Ex{n,}: 최소 n글자 일치해야 한다. (최대는 제한이 없다)
* 4. Ex?: 0번 혹은 한번
* 5. Ex+: 최소 한번 이상
* 6. Ex*: 0번 혹은 여러 번
*/
System.out.println(Pattern.matches("....[\\d]{3}", "abcd123"));
System.out.println(Pattern.matches("[\\w가-힣]{2,12}", "abcd안녕하세요123456"));
String email = "abc@github.io";
System.out.println(Pattern.matches("[\\w]+@[a-zA-z0-9]+[.][a-zA-Z]+", email));
/*
* Pattern.matches(regex, str)
* - 전달한 문자열이 정규표현식과 일치하면 일치하면 true. 일치하지 않으면 false
*
* Matcher
* - 문자열을 처음부터 끝까지 검사해서 해당 정규표현식과 일치하는 인덱스를 찾을 결과를 가지고 있는 객체
*/
}
}
'Programming Language > Java' 카테고리의 다른 글
[국비] Java 내용정리 Day20 (0) | 2021.12.04 |
---|---|
[국비] Java 내용정리 Day18 (0) | 2021.12.01 |
[국비] Java 내용정리 Day17 (0) | 2021.11.29 |
[국비] Java 내용정리 Day16 (0) | 2021.11.28 |
[국비] Java 내용정리 Day15 (0) | 2021.11.25 |
댓글