2023-05-11 목
1. 컬렉션 프레임워크 (Collection Freamwork)
1-1. 컬렉션 프레임 워크란?
다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미합니다.
즉, 데이터를 저장하는 자료구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것을 의미합니다.
이러한 컬렉션 프레임워크는 **자바의 인터페이스 (Interface)**를 사용하여 주로 구현됩니다.
컬렉션 프레임 워크를 사용하면 배열을 사용했을 때보다 조금 더 향상 된 편의 기능을 제공하게 됩니다.
📍 데이터를 담고 처리하는 방법에는 배열(Array)이 있는데 왜 컬렉션(Collection)을 사용하는 걸까요?
그 이유로는 컬렉션의 경우 정적 메모리 할당이 아닌 동적 메모리 할당을 하게 되기 때문입니다.
배열(Array**)은 new int[4]를 하게 되면 4개의 공간만 사용하며 미리 선언을 통해 4개의 공간을 만들어야 하지만,
컬렉션(Collection)은 공간을 필요한 만큼 추가할 수 있다는 장점이 있습니다.
즉, 배열을 사용했을 때보다 조금 더 향상된 편의성을 제공 받게 됩니다.
collection은 공간이 계속 필요한 만큼 추가할 수 있습니다.
1-2. 컬렉션 프레임워크의 상속 구조
컬렉션 프레임워크의 주요 인터페이스의 유형으로는 List형, Set형, Queun형, Map형이 있습니다.
이 중에서 List와 Set, Queun형의 인터페이스는 모두 컬렉션 인터페이스를 상속 받지만, 구조 상의 차이로 인해 Map 인터페이스는 별도로 지정되게 됩니다.
따라서 List와 Set, Queue 인터페이스의 공통된 부분을 Collection 인터페이스에서 정의하고 있고, Map 인터페이스의 경우 Collection 인터페이스를 상속 받고 있지는 않지만 컬렉션으로 분류가 되는 것입니다.
2. List 인터페이스의 특징
2-1.리스트 인터페이스란 ?
배열과 비슷한 동작을 수행하지만, 배열과 달리 크기가 동적으로 조정이 되고 다양한 메소드를 사용하여 데이터 추가, 삭제 등을 쉽게 수행할 수 있습니다.
다양한 구현체
가장 흔히 사용되는 구현체로는
ArrayList, LinkedList가 있습니다.
2-2. 리스트를 써야 하는 이유?
- 크기를 지정하는 것이 유연합니다.
int[]arr = new int[10];
int[] arr2 = {2,3,4};
배열의 경우 선언 할 때 크기를 반드시 지정해줘야 하며, 선언 후 길이 조정이 불가능하기 때문에 새로운 배열을 만들어야 하는 어려움이 있습니다.
- List 활용 예제1
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
int[] arr = new int[10]; // 배열은 크기 지정이 필수적이다.
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
// list의 길이만큼 temp 배열에 크기를 할당할수 있습니다. (유동적으로 사용 가능)
int[] temp = new int[list.size()];
}
}
배열 (Array)와 달리 다양한 메소드를 제공합니다.
주로 사용하는 리스트 코드 예시
.get(int index) → 지정된 인덱스에 위치의 값을 반환합니다.
.add(element) → List의 끝에 원소를 삽입합니다.
.size() → List의 원소갯수 ( 길이 )를 반환합니다.
.remove() → List에 들어있는 인덱스 삭제합니다.
!!! 아래의 코드처럼 .remove() 는 주의해야 합니다.“Hello” 라는 값, 1 이라는 값이 List의 0번인덱스 1번 인덱스로 add가 되었는데 remove() 에서는 0 번 인덱스만 삭제하는 것입니다..
remove()의 특징은 해당 인덱스를 지우고, 남은 요소들의 인덱스를 앞으로 한칸 씩 땡긴다는 것입니다.
.isEmpty() → 비어 있는지 여부를 반환합니다.
(Empty인 경우 true ) ( 논리값으로 반환 됩니다. )
.iterator () → == repeator (리피터) 반복할 수 있는, for문을 쓸 수 있다.
- List 활용 예제
import java.util.ArrayList;
import java.util.List;
public class ListEx {
public static void main(String[] args) {
List l1 = new ArrayList();
l1.add("Hello"); //0번 인덱스
l1.add("1"); //1번 인덱스
l1.remove(0); //인덱스의 0번 삭제
l1.remove(0); //인덱스의 0번 삭제
System.out.println(l1.size()); // 0
}
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListEx {
public static void main(String[] args) {
List myList = new ArrayList<>();
myList.add("Apple");
myList.add("Banana");
myList.add("Orange");
// iterator 선언
Iterator iterator = myList.iterator();
// hasNext() : 다음 원소의 존재 여부를 반환합니다. (논리값 반환)
while (iterator.hasNext()) {
// 제네릭을 지정하지않아, 강제 형변환을 해줘야합니다. (안좋은 방법)
String element = (String) iterator.next();
System.out.println(element);
}
}
}
- List 활용 예제2 (제네릭을 사용하지 않고 작성한 코드 )
public class ListEx {
public static void main(String[] args) {
List l1 = new ArrayList();
l1.add("Hello"); //0번 인덱스
l1.add("1"); //1번 인덱스
System.out.println(l1.get(0)); // li 리스트의 0번 인덱스를 가져온다.
System.out.println(l1.get(1));
System.out.println(l1.size()); //리스트에 사이즈
System.out.println(l1.isEmpty()); //리스트에 값이 비어있는지 (논리값으로 반환)
l1.remove(0); //인덱스의 0번 삭제
l1.remove(0); //인덱스의 0번 삭제
System.out.println(l1.isEmpty());
}
}
실행결과
Hello
1
2
false
true
- 다양한 데이터 유형을 저장할 수 있습니다.
- 객체를 반환 타입으로 가지는 리스트 활용 예제
import java.util.ArrayList;
import java.util.List;
class Student {
// 멤버변수는 private으로 선언
private String name;
private String passWord;
private int age;
public String getName() {
return name;
}
public String getPassWord() {
return passWord;
}
public int getAge() {
return age;
}
public Student(String name, String passWord, int age) {
this.name = name;
this.passWord = passWord;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student("abc", "123456", 25);
List<Student> students = new ArrayList<>();
// List에 객체를 add 해준다.
students.add(student);
System.out.println("학생의 이름은 : " + student.getName());
System.out.println("학생의 비밀번호는 : " + student.getPassWord());
System.out.println("학생의 나이는 : " + student.getAge());
}
}
학생의 이름은 : abc
학생의 비밀번호는 : 123456
학생의 나이는 : 25
for each (향상된 for 문)
System.out.println("----------");
for (var item : l1){ //==for each
System.out.println(item);
}
Hello
1
3-1. LinkedList란?
: List 인터페이스를 구현한 클래스 중 하나입니다. 데이터의 순서를 유지하는 특징이 있습니다.
3-2. LinkedList 의 장점
- 순차 접근만 가능 (페이지가 없는 책)
- 인덱스 접근 불가 (예시) 몇번째, ~개 중 ~번째 x)
- 장점은 데이터를 추가와 삭제 할 때 좋습니다.
4. 제네릭(Generic)
4-1. 제네릭이란 ?
컬렉션에 타입을 지정해주는 기능입니다.
구체적으로 해당 컬렉션에 어떤 타입의 원소가 저장될 것인지 선언 해주는 것입니다.
예) 반 ,학과
4-2. List<참조 타입>
- 왜 참조 타입만 사용이 가능한가? → JAVA에서는 heap에 객체를 생성함으로, 객체를 참조하기 위해서는 heap에 생성되는 타입이 필요합니다. ※ JAVA에서는 원시 타입은 stack 영역에 생성되고, 참조 타입은 heap 영역에 생성됩니다.
📍 제네릭을 사용하지 않는다면, 자료형과 관련된 메소드를 사용할 때 마다 사용하려는 자료형으로 타입 캐스팅을 해야 하는 번거로움이 발생합니다.
제네릭 활용 예시
public class GenericEx {
public static void main(String[] args) {
List<String> strList = new ArrayList<>();
//여기서 "< >" 사이의 String이 제네릭이다.
strList.add("Hello");
strList.add("Bye");
strList.add("1");
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
for (String item : strList) {
//제네릭 덕분에 iterator의 사용이 가능하다.
System.out.println(item);
}
for (int item : intList) {
System.out.println(item);
}
}
}
Hello
Bye
1
1
2
5. Constructor, Getter& Setter
5-1. Constructor
클래스를 인스턴스화 할 때 호출되는 메소드입니다.
**** 생성자의 경우 몇가지의 규칙이 있습니다.**
- 생성자의 이름은 클래스의 이름과 같아야 한다.
- 생성자는 리턴 값이 없다. void 또한 사용하지 않는다.
- 생성자는 반드시 클래스 내부에 선언되어야 하며, 접근 제한자를 사용할 수 있다.
- 클래스에 생성자를 정의하지 않으면 컴파일러가 자동으로 기본 생성자를 만들어 준다.
- 아무 것도 하지 않고, 매개변수가 없는 빈 메소드이다.
5-2. Getter & Setter
오브젝트의 멤버 변수에 직접 접근하는 방법을 피하기 위해 사용합니다.
- 직접 접근을 막음으로써 객체의 정보를 보호하여 안정성을 높일 수 있습니다
- 예시 :
- 비밀번호
- 전화번호
- 이메일
5-3. Getter 란?
현재 오브젝트의 맴버 변수가 지니고 있는 값을 가져오는(Get) 메소드입니다.
- 가져오려는 매개변수의 타입을 리턴 합니다.
5-4. Setter 란?
현재 오브젝트의 맴버 변수에 임의의 값을 할당하는(Set) 메소드입니다.
- 값을 할당하기만 하기에 void 타입을 리턴 합니다.
- Constructor, Getter& Setter 활용 예시
class Student{
private String name;
private String passWord;
private int age;
// Constructor
public Student(String name, String password, int age){
this.name = name;
this.password = password;
this.age = age;
}
public String getName() {
// Student 객체의 name 매개변수를 가져옵니다
return name;
}
public void setName(String name){
// Student 객체(this)의 name 매개변수를 할당합니다
this.name = name;
}
public void setPassWord(String password) {
// Student 객체(this)의 password 매개변수를 할당합니다
this.password = password;
}
public void setAge(int age) {
this.age = age;
}
public boolean isAdult(){
return age >= 18;
}
}
📍 Getter 와 Setter는 항상 한 쌍으로 생성되어야 할 이유는 없습니다. 위의 예시 같은 경우, age의 경우는 성인과 미성년자를 구분하는 역할을 하기 때문에, age를 활용한 메소드 isAdult만 만들고, 값을 불러오는 getAge는 불필요 합니다.
6. 알고리즘 실습 (Codeup 3108번)
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Student {
private String code;
private int testId; // String -> int 로 바뀌었는데 나중 결과보고 수정...
private String name;
// 멤버변수에 직접 접근하는 것을 막기 위해 생성자를 만든다
public Student(String code, String testId, String name) {
this.code = code;
this.testId = Integer.parseInt(testId);
this.name = name;
}
// Getter
public String getCode() {
return code;
}
public int getTestId() {
return testId;
}
public String getName() {
return name;
}
}
// 이하 main method
public class CodeUp3108 {
private List<Student> students = new ArrayList<>();
public Student makeAStudent(String code, String testNum, String name) {
// 입력 받은 값을 Object로 만들어 줌
return new Student(code, testNum, name);
}
// 수험번호 중복 화인
private boolean isExist(Student pStudent) {
for (Student student :
students) {
if (pStudent.getTestId() == student.getTestId()) return true;
}
return false;
}
// 리스트에 학생 추가
private void addAStudent(Student student) {
if (!isExist(student)) {
students.add(student);
}
}
// 리스트에 학생 삭제
private void deleteStudent(Student pStudent) {
for (int i = 0; i < students.size(); i++) {
if(students.get(i).getTestId() == pStudent.getTestId()) students.remove(i);
}
}
// code가 I일 경우 학생추가
// code가 D일 경우 학생삭제
public void process(Student pStudent) {
switch (pStudent.getCode()) {
case "I" -> addAStudent(pStudent);
case "D" -> deleteStudent(pStudent);
if(pStudent.getCode().equals("I")){
addAStudent(pStudent);
}else{
deleteStudent(pStudent);
}
}
// print기능
private void printStudents(String[] indexList) {
for (int i = 0; i < indexList.length; i++) {
int index = Integer.parseInt(indexList[i]) - 1;
System.out.printf("%d %s\\n",students.get(index).getTestId() ,students.get(index).getName());
}
}
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
int count = sc. nextInt();
sc.nextLine();
CodeUp3108 codeUp3108 = new CodeUp3108();
for (int i = 0; i < count; i++) {
codeUp3108.process(codeUp3108.makeAStudent(sc.next(),sc.next(),sc.next()));
}
sc.nextLine();
String[] indexList = sc.nextLine().split(" ");
codeUp3108.students.sort((s1, s2) -> Integer.compare(s1.getTestId(), s2.getTestId()));
codeUp3108.printStudents(indexList);
}
}
7. 파싱(Parsing)
7-1. 파싱(Parsing)이란?
웹페이지에서 원하는 데이터를 추출하여 가공하기 쉬운 상태로 바꾸는 것으로 내가 원하는 대로 가공하여 서버에서 원하는 때 불러 올 수 있도록 하는 것입니다.
즉, 데이터를 분해 분석하여 원하는 형태로 조립하고 다시 빼내는 프로그램이라고 하기도 합니다.
웹사이트 상에서 주어진 정보를 원하는 형태로 가공하여 서버에서 불러 들이는 것을 말하며,
대표적인 파싱 기법으로는 XML Parsing과 JSON Parsing이 있습니다.
7-2. 파서(Parser)란?
컴파일러나 인터프리터 등과 같은 원시 프로그램을 읽어 들여 그 문장의 구조를 알아내는 구문 분석을 하는 프로그램입니다.
즉, 원시 프로그램의 명령문이나 온라인 명령문, HTML 문서 등에서 Markup Tag 등을 입력으로 받아들여 구문을 해석할 수 있는 단위로 여러 부분을 분활해 주는 역할이라고도 합니다.
📍 원시 프로그램이란? 기계어로 변역 되기 전의 프로그램을 말합니다