1.5 Iterator
- 컬렉션에 저장된 요소 접근에 사용
- iterator() : iterator 반환 메소드
- 컬렉션에 정의=> 자손인 List/Set에도 호출 가능
- List : 순서가 저장됨
- Set : 순서가 저장x
- Map은 직접호출 불가 => EntrySet이나 keySet로 collection 얻어온 후, 호출 가능
>>메서드
ex)
package ch11;
import java.util.*;
public class IteratorEx1 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
Iterator it= list.iterator();
while(it.hasNext()){
Object obj= it.next();
System.out.println(obj);
}
}
}
>>실행결과
1
2
3
4
5
>> ListIterator
: 양방향으로 이동이 가능
: 이동하기 전에 hasNext() / hasPrevious() 를 통해 읽어올 객체가 있는지 확인해야 함
ex)
package ch11;
import java.util.*;
public class IteratorEx1 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
ListIterator lit= list.listIterator();
while(lit.hasNext()){
Object obj= lit.next();
System.out.print(obj+" ");
}
System.out.println();
while(lit.hasPrevious()){
Object obj = lit.previous();
System.out.print(obj+" ");
}
}
}
>>실행결과
1 2 3 4 5
5 4 3 2 1
>> remove는 단독으로 쓰일 수 없고 next()와 함께 쓰여야 함
- 즉, 읽어온 것을 삭제함
- next() 호출없이 remove()를 호출하면 IllegalStateException이 발생됨
public class IteratorEx2 {
public static void main(String[] args) {
ArrayList original= new ArrayList(10);
ArrayList copy1 = new ArrayList(10);
ArrayList copy2= new ArrayList(10);
for (int i = 0; i < 10; i++) {
original.add(i+"");
}
Iterator it= original.iterator();
while(it.hasNext()){
copy1.add(it.next());
}
System.out.println("=Original에서 copy1로의 복사=");
System.out.println("origianl : " + original);
System.out.println("copy1 : "+ copy1);
System.out.println();
it= original.iterator();
while(it.hasNext()){
copy2.add(it.next());
it.remove(); //읽은 값을 삭제
}
System.out.println("=Original에서 copy1로의 복사=");
System.out.println("origianl : " + original);
System.out.println("copy2 : "+ copy2);
}
}
>>실행결과
=Original에서 copy1로의 복사=
origianl : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
copy1 : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
=Original에서 copy1로의 복사=
origianl : []
copy2 : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1.6 Arrays
- 배열을 다루는데 유용한 메서드
1. 배열의 복사 : copyOf(), copyOfRange()
2. 배열 채우기 : fill() / setAll()
- fill(배열, 값) : 배열을 모두 값으로 채움
- setAll(배열, 람다식/함수형 인터페이스) : 배열에 모두 메서드 호출
3. 배열의 정렬과 검색 : sort() / binarySearch()
-binearySearch() : 이진탐색은 반드시 정렬된 상태에서 해야 올바른 결과를 얻음
4. 배열의 비교와 출력 : equals() / toString()
>> 다차원 배열의 비교 => deepEquals()/ deepToString()
=> 재귀적으로 equals와 toString을 호출
- 다차원 배열에서 equals를 하면 각 주소값이 호출되며 false가 나옴
- deepEquals를 해야 재귀적으로 equals가 호출되며 값을 온전히 비교
5. 리스트로 변환 : asList()
=> but, asList가 반환한 리스트의 경우, 크기를 변경할 수가 없음(추가/삭제가 불가함)
=> ArrayList로 변경해주어야 가능
ex)
package ch11;
import java.util.*;
public class ArrayEx {
public static void main(String[] args) {
int [] arr= {0,1,2,3,4};
int [][] arr2D ={{11,12,13}, {21,22,23}};
System.out.println("arr="+ Arrays.toString(arr));
System.out.println("arr2D="+ Arrays.deepToString(arr2D));
//arr=[0, 1, 2, 3, 4]
//arr2D=[[11, 12, 13], [21, 22, 23]]
int [] arr2= Arrays.copyOf(arr, arr.length);
int [] arr3= Arrays.copyOf(arr, 3);
int [] arr4 = Arrays.copyOf(arr, 7);
int [] arr5 = Arrays.copyOfRange(arr, 2,4);
int [] arr6 = Arrays.copyOfRange(arr, 0,7);
System.out.println("arr2= "+ Arrays.toString(arr2));
System.out.println("arr3= "+ Arrays.toString(arr3));
System.out.println("arr4= "+ Arrays.toString(arr4));
System.out.println("arr5= "+ Arrays.toString(arr5));
System.out.println("arr6= "+ Arrays.toString(arr6));
//arr2= [0, 1, 2, 3, 4]
//arr3= [0, 1, 2]
//arr4= [0, 1, 2, 3, 4, 0, 0]
//arr5= [2, 3]
//arr6= [0, 1, 2, 3, 4, 0, 0]
int [] arr7= new int[5];
Arrays.fill(arr7, 9);
System.out.println("arr7=" + Arrays.toString(arr7));
Arrays.setAll(arr7, i-> (int) (Math.random()*6)+1);
System.out.println("arr7= "+Arrays.toString(arr7));
//arr7=[9, 9, 9, 9, 9]
//arr7= [3, 1, 1, 5, 4]
for(int i: arr7){
char [] graph = new char[i];
Arrays.fill(graph, '*');
System.out.println(new String(graph)+i);
}
//***3
//*1
//*1
//*****5
//****4
String [][] str2D= new String [][] {{"aaa", "bbb"}, {"AAA", "BBB"}};
String [][] str2D2 = new String [][] {{"aaa", "bbb"}, {"AAA", "BBB"}};
System.out.println(Arrays.equals(str2D, str2D2)); //false
System.out.println(Arrays.deepEquals(str2D, str2D2)); //true
char [] chArr= {'A','D','C', 'B', 'E'};
System.out.println("chArr = "+ Arrays.toString(chArr));
System.out.println("index of B ="+ Arrays.binarySearch(chArr, 'B'));
System.out.println("=After sorting =");
Arrays.sort(chArr);
System.out.println("chArr="+Arrays.toString(chArr));
System.out.println("index of B="+ Arrays.binarySearch(chArr, 'B'));
//chArr = [A, D, C, B, E]
//index of B =-2 => 정렬을 안해서 이상한 값으로 나옴
//=After sorting =
//chArr=[A, B, C, D, E]
//index of B=1
}
}
1.7 Comparator와 Comparable
- 객체 정렬하는데 필요한 메서드를 정의한 인터페이스
- compare/ compareTo는 두 객체의 비교결과를 반환 => 작으면 0 오른쪽이 크면 - / 작으면 +
ex)
public class comparatorEx {
public static void main(String[] args) {
String [] strArr ={"cat", "Dog", "lion", "tiger"};
Arrays.sort(strArr);
System.out.println("strArr="+ Arrays.toString(strArr));
Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER);//대소문자 구분x
System.out.println("strArr="+ Arrays.toString(strArr));
Arrays.sort(strArr, new Descending());
System.out.println("strArr="+ Arrays.toString(strArr));
}
}
class Descending implements Comparator{
public int compare(Object o1, Object o2){
if( o1 instanceof Comparable && o2 instanceof Comparable){
Comparable c1= (Comparable)o1;
Comparable c2= (Comparable)o2;
return c1.compareTo(c2)*-1;
}
return -1;
}
}
>>실행결과
strArr=[Dog, cat, lion, tiger]
strArr=[cat, Dog, lion, tiger]
strArr=[tiger, lion, cat, Dog]
-1) sort(strArr) => 대소문자 구분하며 정렬
-2) sort(strArr, String.CASE_INSENSTIVE_ORDER) => 대소문자 구분하지 않고 정렬
-3) sort(strArr, new Descending()) => 기본 정렬의 역순(-1을 곱함)
1.8 SET : HashSet / TreeSet
--HashSet
: 순서x / 중복x
: 순서를 유지하려면 => LinkedHashSet을 사용해야 함
: boolean add(Object o) => 중복된 요소 추가시 false반환
>>생성자
HashSet() | HashSet 객체를 생성한다. |
HashSet(Collection c) | 주어진 컬렉션을 포함하는 HashSet 객체를 생성한다. |
HashSet(int initialCapacity) | 주어진 값을 초기용량으로 하는 HashSet 객체를 생성한다. |
HashSet(int initialCapacity, float loadFactor) | 초기용량과 load factor를 지정하는 생성자 |
>>메서드
메서드 | 설명 |
boolean add(Object o) boolean addAll(Collection c) |
- 객체를 추가 / 성공하면 true - 주어진 컬렉션에 저장된 모든 개게를 추가(합집합) |
boolean remove(Object o) boolean removeAll(Collection c) |
- 객체를 삭제 / 성공하면 true - Collection에 있는 요소들을 set에서 모두 삭제 / 성공하면 true |
void clear() | Set을 비우기 |
Object clone() | Set을 복제해서 반환(얕은 복사) |
boolean contains(Object o) boolean containsAll(Collection c) |
- 객체를 포함하는지 확인 - 컬렉션의 요소들을 모두 포함하는지 확인 |
boolean isEmpty() | Set이 비었는지 |
Iterator iterator() | Iterator 반환 |
boolean retainAll(Collection c) | 교집합만을 남기 |
int size() | 저장된 객체의 개수를 반환 |
Object [] toArray() Object [] toArray(Object [] a) |
-저장된 객체들을 객체배열의 형태로 만듦 - 반환 객체배열을 a에 담음 |
>>문제 : equals가 인스턴스에 대해 주소값으로 판단됨
- equals와 hashCode 오버라이딩을 통해 중복요소 판단에 대한 부분을 정의 가능
ex)
package ch11;
import java.util.*;
public class HashSetEx1 {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add("abc");
set.add("abc");
set.add(new Person("David", 10));
set.add(new Person("David", 10));
System.out.println(set);
}
}
class Person{
String name;
int age;
Person(String name, int age){
this.name= name;
this.age=age;
}
public String toString(){
return name+":"+age;
}
}
>>실행결과
[David:10, David:10, abc]
=> 두 객체의 주소값이 다르기에 다른 요소로 판단
=> 그럼 두 객체를 같은 것으로 인식하게 하기 위해서는 어떻게 해야하나?
== hashCode와 equals오버라이딩
ex2)
package ch11;
import java.util.*;
public class HashSetEx1 {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add("abc");
set.add("abc");
set.add(new Person("David", 10));
set.add(new Person("David", 10));
System.out.println(set);
}
}
class Person{
String name;
int age;
Person(String name, int age){
this.name= name;
this.age=age;
}
public String toString(){
return name+":"+age;
}
public boolean equals(Object obj){
if(obj instanceof Person){
Person p= (Person)obj;
return name.equals(p.name) && age==p.age;
}
return false;
}
public int hashCode(){
return Objects.hash(name, age);
}
}
>>실행결과
[David:10, abc]
>> hashCode() 오버라이딩 시 유의사항
1) 동일 객체에 대해 hashCode를 여러번 호출해도 동일한 값을 반환
2) equals로 비교해서 true를 얻은 두 객체의 hashCode값은 일치해야 함
=> 같다고 판단한 것은 hash도 같아야 함
3) equals로 비교한 결과가 false인 두 객체의 hashCode()값은 같을 수 있음
=> hash는 더 넓은 범위를 작은 범위에 대응시키기 때문
ex3)
package ch11;
import java.util.*;
public class HashSetEx2 {
public static void main(String[] args) {
HashSet setA = new HashSet();
HashSet setB = new HashSet();
HashSet setHab = new HashSet();
HashSet setKyo = new HashSet();
HashSet setCha = new HashSet();
setA.add("1");setA.add("2");setA.add("3");setA.add("4");setA.add("5");
setB.add("4");setB.add("5");setB.add("6");setB.add("7");setB.add("8");
Iterator it = setB.iterator();
//교집합
while(it.hasNext()){
Object tmp= it.next();
if(setA.contains(tmp)){
setKyo.add(tmp);
}
setHab.add(tmp);
}
it= setA.iterator();
//차집합
while(it.hasNext()){
Object tmp= it.next();
if(!setB.contains(tmp)){
setCha.add(tmp);
}
setHab.add(tmp);
}
System.out.println("교집합="+setKyo);
System.out.println("합집합="+setHab);
System.out.println("차집합="+setCha);
}
}
>>실행결과
교집합=[4, 5]
합집합=[1, 2, 3, 4, 5, 6, 7, 8]
차집합=[1, 2, 3]
>>TreeSet
: 이진 검색트리로 이루어짐
: 정렬, 검색, 범위검색에 높은 성능을 보임
: 중복된 데이터 저장을 허용x + 정렬된 위치에 저장
: 부모보다 작은 값을 왼쪽에 큰 값은 오른쪽에
: HashSet보다 데이터 추가, 삭제에 시간이 더 걸림
>>데이터 저장과정
ex) 7 - 4 - 9 - 1 - 5 과정
-> 컴퓨터는 알아서 값을 비교하지 못함
-> TreeSet에 저장되는 객체가 Comparable을 구현 or Comparator를 TreeSet에게 제공
>> 생성자와 메서드
>>범위검색 예제
import java.util.*;
public class TreeSetEx1 {
public static void main(String[] args) {
TreeSet set = new TreeSet();
String from ="b";
String to="d";
set.add("abc"); set.add("alien"); set.add("bat");
set.add("car"); set.add("Car"); set.add("disc");
set.add("dance"); set.add("dZZZZ"); set.add("dzzzzz");
set.add("elephant"); set.add("elevator"); set.add("fan");
set.add("flower");
System.out.println(set);
System.out.println("range search : from " + from + " to "+ to);
System.out.println("result1 : "+ set.subSet(from, to));
System.out.println("result2 : "+ set.subSet(from, to+"zzz"));
}
}
>>실행결과
[Car, abc, alien, bat, car, dZZZZ, dance, disc, dzzzzz, elephant, elevator, fan, flower]
range search : from b to d
result1 : [bat, car]
result2 : [bat, car, dZZZZ, dance, disc]
ex2) headSet / tailSet
public class TreeSetEx2 {
public static void main(String[] args) {
TreeSet set= new TreeSet();
int [] score={80,95,50,35,45,65,10,100};
for (int i = 0; i <score.length ; i++) {
set.add(score[i]);
}
System.out.println("50보다 작은 값 : "+ set.headSet(50));
System.out.println("50보다 큰 값 : "+ set.tailSet(50));
}
}
>>실행결과
50보다 작은 값 : [10, 35, 45]
50보다 큰 값 : [50, 65, 80, 95, 100]
=> 오토박싱되므로 new Integer(50)을 안해주어도 됨
'기술 서적 > 자바의 정석' 카테고리의 다른 글
[자바의 정석] ch12. Generics / enums / annotation (0) | 2024.01.22 |
---|---|
[자바의 정석] ch11-3.컬렉션 프레임워크 : HashMap/TreeMap / Collections (0) | 2024.01.20 |
[자바의 정석] ch11-1 : 컬렉션프레임워크 -- List / Stack-Queue (0) | 2024.01.14 |
[자바의 정석] ch9-1. java.lang 패키지와 유용한 클래스 (0) | 2024.01.09 |
[자바의 정석] ch8. 예외처리 (0) | 2024.01.06 |