<T> : 타입
<E> : 요소(자료구조 내부에 저장되는 요소의 타입)
<K> : key
<V> : value










T는 Material 하위클래스로 특정해서 지정하는 방법
public class GenericPrinterExtends<T extends Material> {
private T material;
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
}
public class GenericPrinterExtendsTest {
public static void main(String[] args) {
Aluminum al = new Aluminum();
GenericPrinterExtends<Aluminum> printer1 = new GenericPrinterExtends<>();
printer1.setMaterial(al);
System.out.println(printer1.getMaterial());
Aluminum p = printer1.getMaterial();
System.out.println(p);
System.out.println("=================");
Plastic pl = new Plastic();
GenericPrinterExtends<Plastic> printer2 = new GenericPrinterExtends<>();
printer2.setMaterial(pl);
System.out.println(printer2.getMaterial());
Plastic p2 = printer2.getMaterial();
System.out.println(p2);
System.out.println("=================");
p2.print();
//GenericPrinterExtends<Coffee> printer3 = new GenericPrinterExtends<>();
}
}

public class Point<T,V> {
T x; //x좌표 - left,right로 표현(실수나 정수가 올 수 있다)
V y; //y좌표 - top,bottom을 표현
public Point(T x, V y) {
super();
this.x = x;
this.y = y;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public V getY() {
return y;
}
public void setY(V y) {
this.y = y;
}
}
public class GenericMethodTest {
//사각형의 면적을 계산해서 리턴하는 메소드
//메소드 안에서 사용할 제네릭의 기호를 리턴타입 옆에 정의
public static<T,V> double genericTest(Point<T, V> p1, Point<T, V> p2) {
double result = 0.0;
double left = ((Number) p1.getX()).doubleValue();
double top = ((Number) p1.getY()).doubleValue();
double right = ((Number) p2.getX()).doubleValue();
double bottom = ((Number) p2.getY()).doubleValue();
double width = right - left;
double height = bottom - top;
result = width * height;
return result;
}
public static<T1,V1,T2,V2> double genericTest2(Point<T1, V1> p1, Point<T2, V2> p2) {
double result = 0.0;
double left = ((Number) p1.getX()).doubleValue();
double top = ((Number) p1.getY()).doubleValue();
double right = ((Number) p2.getX()).doubleValue();
double bottom = ((Number) p2.getY()).doubleValue();
double width = right - left;
double height = bottom - top;
result = width * height;
return result;
}
public static void main(String[] args) {
Point<Integer,Double> point1 = new Point<Integer, Double>(10, 10.5);
Point<Integer,Double> point2 = new Point<Integer, Double>(25, 30.8);
Point<Integer,Double> point3 = new Point<Integer, Double>(10, 10.5);
Point<Float,Long> point4 = new Point<Float,Long>(30.8F, 25L);
double rectArea = genericTest(point1, point2);
double rectArea2 = genericTest2(point3, point4);
System.out.println("면적은 "+rectArea+"이다.");
System.out.println("면적은 "+rectArea2+"이다.");
}
}

generic 연습
연산할 숫자를 가지고 있는 클래스
public class MyNum<T> {
T num1;
T num2;
public MyNum(T num1, T num2) {
super();
this.num1 = num1;
this.num2 = num2;
}
public T getNum1() {
return num1;
}
public void setNum1(T num1) {
this.num1 = num1;
}
public T getNum2() {
return num2;
}
public void setNum2(T num2) {
this.num2 = num2;
}
}
public class Opr {
public <T> double add(MyNum<T> numObj) {
double num1 = ((Number) numObj.getNum1()).doubleValue();
double num2 = ((Number) numObj.getNum2()).doubleValue();
return num1+num2;
}
public <T> double sub(MyNum<T> numObj) {
double num1 = ((Number) numObj.getNum1()).doubleValue();
double num2 = ((Number) numObj.getNum2()).doubleValue();
return num1-num2;
}
public <T> double mul(MyNum<T> numObj) {
double num1 = ((Number) numObj.getNum1()).doubleValue();
double num2 = ((Number) numObj.getNum2()).doubleValue();
return num1*num2;
}
public <T> double div(MyNum<T> numObj) {
double num1 = ((Number) numObj.getNum1()).doubleValue();
double num2 = ((Number) numObj.getNum2()).doubleValue();
return num1/num2;
}
}
public class GenericExamTest {
public static void main(String[] args) {
MyNum<Integer> numObj1 = new MyNum<Integer>(100, 50);
MyNum<Double> numObj2 = new MyNum<Double>(50.9, 20.8);
Opr opr = new Opr();
System.out.println(opr.add(numObj1));
System.out.println(opr.mul(numObj1));
System.out.println("----------------");
System.out.println(opr.add(numObj2));
System.out.println(opr.sub(numObj2));
}
}

//CompareTo메소드
public class CompareToTest {
public static void main(String[] args) {
System.out.println((int)'A');
//작은따옴표로 하는 이유(문자 하나 char)
//"" : String , '' : char
Integer i = 10;
Integer j = 20;
Integer k = 5;
Integer num = 10;
System.out.println(i.compareTo(j));//-1 : i가 비교대상의 값보다 작은 경우
System.out.println(i.compareTo(k));//1 : i가 비교대상의 값보다 큰 경우
System.out.println(i.compareTo(num));//0 : i가 비교대상의 값과 같은 경우
String str0 = "B";
String str1 = "A";//65
String str2 = "B";//66 - 기준값
String str3 = "C";//67
String str4 = "D";//68
String str5 = "E";//69
String mystr = "test2";
System.out.println("===============문자열비교================");
System.out.println(str2.compareTo(str0));//0 - 같은 문자열
//System.out.println(mystr.compareTo("test2"));//0 - 같은 문자열
System.out.println(str2.compareTo(str1));//str2가 B(66)이고 str1이 A(65) => 1
System.out.println(str2.compareTo(str3));//66-67 = -1
System.out.println(str2.compareTo(str4));//66-68 = -2
System.out.println(str2.compareTo(str5));//66-69 = -3
System.out.println("E".compareTo("A"));//69-65 = 4
}
}

public class MyNode<E> {
private E data;//저장될데이터
MyNode<E> nextNode;//참조하게될 다음 노드 정보 - 참조할 노드가 없는 경우에는 null이 할당
public MyNode() {
data = null;
nextNode = null;
}
public MyNode(E data) {
this.data = data;
this.nextNode = null;
}
public MyNode(E data, MyNode<E> nextNode) {
super();
this.data = data;
this.nextNode = nextNode;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
}
public class MyLinkedList<E> {
private MyNode<E> head;//첫번째 노드를 헤드라고 부른다.(헤드에 노드를 직접 저장)
int size;//링크드리스트에 몇개가 저장되어있는지를 표현할 변수
public MyLinkedList() {
head = null;
size = 0;
}
//맨마지막에 노드를 삽입하는 작업 처리
//맨 마지막까지 쭉 찾아가서 (순회) 요소를 저장하는데 맨 마지막 요소는 참조하는 노드가 null이다.
public MyNode<E> add(E data) {
//추가될 노드
MyNode<E> newNode = null;
//head가 널인지 체크. 널이라는 것은 첫번째 노드라는 의미이므로 head에 추가하는 작업부터 시작
if(head==null) {
//노드를 만들고
newNode = new MyNode<>(data);
//헤드에 셋팅
head = newNode;
}else {
//head가 널이 아니라는 것은 이미 head에 노드가 셋팅됐다는 의미이므로 노드들을 순회해서 마지막까지 찾아가서
//마지막 노드에 추가
newNode = new MyNode<>(data);
//맨 마지막 노드를 찾기 위해서 노드를 순회해야 한다.
//노드를 찾아가기 위해서 노드가 있어야 하므로 head부터 찾아가면 된다.
//템프노드는 중간에 순회하는 노드를 넣으려고 임시로 선언한 노드
//else블럭에 넣고 while문을 돌리면서 순회하는대로 찾는 노드를 넣을것
MyNode<E> tempNode = head;
while(tempNode.nextNode!=null) {
tempNode = tempNode.nextNode;
}
//tempNode는 nextNode가 널인상태 => 즉 마지막 노드라는 의미
tempNode.nextNode = newNode;
}
size++;
return newNode;
}
public void printAll() {
//모든 연결된 노드를 순회하며 data를 출력하기
//data -> data -> ...
MyNode<E> tempNode = head;
while(tempNode!=null) {
System.out.print(tempNode.getData());
tempNode = tempNode.nextNode;//그다음 노드를 순회하기 위해 넘겨주기
if(tempNode!=null) {//마지막 노드가 아니면
System.out.print("->");
}
}
System.out.println();
}
public boolean isEmpty() {
if(head==null) {
return true;
}else {
return false;
}
}
public int getSize() {
return size;
}
public void removeAll() {
head = null;
size = 0;
}
public MyNode<E> insert(int position, E data) {
//첫번째 노드부터 순회하며 삽입될 위치로 찾아가야 함
MyNode<E> tempNode = head;
MyNode<E> newNode = new MyNode<>(data);
if(position==0) {
newNode.nextNode = head;//원래 헤드에 있던 노드 뉴노드의 다음 노드에 삽입
head = newNode;//새로운 노드 헤드에 삽입
}else {
MyNode<E> preNode = null;
//삽입될 위치의 이전 노드의 포지션을 찾아 작업하기
for(int i=0;i<position;i++) {
preNode = tempNode;
//노드를 순회하면서 다음 참조하는 노드를 tempNode로 지정 - 계속 찾아나가기 위해서 작업
tempNode = tempNode.nextNode;
}
//새 노드의 nextNode를 현재 preNode의 nextNode로 설정
newNode.nextNode = preNode.nextNode;
//preNode의 nextNode를 새 노드로 설정
preNode.nextNode = newNode;
}
size++;
return newNode;
}
public MyNode<E> remove(int position){
MyNode<E> tempNode = head;
//맨앞의 노드를 삭제하는 경우
if(position==0) {
head = tempNode.nextNode;
}else {
MyNode<E> preNode = null;
for(int i=0;i<position;i++) {
preNode = tempNode;
tempNode = tempNode.nextNode;
}
preNode.nextNode = tempNode.nextNode;
}
size--;
System.out.println(position+"항목이 삭제됐습니다.");
return tempNode;
}
}
public class MyLinkedListTest {
public static void main(String[] args) {
MyLinkedList<String> list = new MyLinkedList<>();
list.add("사과");
list.add("배");
list.add("바나나");
list.printAll();//전체 LinkedList의 모든 데이터를 출력
System.out.println("-------------");
list.insert(2,"수박");
list.printAll();//사과->배->수박->바나나
System.out.println("-------------");
list.remove(1);
list.printAll();//사과->수박->바나나
}
}

printAll완성하기(printAll의 실행결과를 캡쳐해주세요)
insert메소드를 구현해서 중간에 원하는 노드가 삽입될 수 있도록 구현하세요
remove완성하기

본 포스팅은 멀티캠퍼스의 멀티잇 백엔드 개발(Java)의 교육을 수강하고 작성되었습니다.