핵심 인터페이스
인터페이스 | 특징 |
---|---|
List | 순서가 있는 데이터의 집합. 데이터의 중복을 허용한다.(순서 o, 중복 o) 구현 클래스 : ArrayList, LinkedList, Stack, Vector 등 |
Set | 순서를 유지하지 않는 데이터의 집합. 데이터의 중복을 허용하지 않는다.(순서 x, 중복 x) 구현 클래스 : HashSet, TreeSet 등 |
Map | 키와 값의 쌍으로 이루어진 데이터의 집합, 순서는 유지되지 않으며, 키는 중복을 허용하지 않고, 값은 중복을 허용한다. (순서 x, 키(아이디)중복 x, 값(비밀번호) 중복 o 구현 클래스 : HashMap, TreeMap, Hashtable, Properties 등 |
메서드 실습
public class ArrayListTest {
public static void main(String[] args) {
ArrayList list1 = new ArrayList(10); // ArrayList 크기 선언
list1.add(new Integer(5)); // ArrayList는 객체만 저장가능
list1.add(4); // 컴파일러가 자동으로 autoboxing 해줌
list1.add(2);
list1.add(0);
list1.add(1);
list1.add(3);
ArrayList list2 = new ArrayList((list1.subList(1,4))); // index 1<= x <4 사이의 값 반환
print(list1,list2);
// 결과 : list1 :[5, 4, 2, 0, 1, 3]
// list2 :[4, 2, 0]
// Collection은 인터페이스, Collections는 클래스
Collections.sort(list1); // list1,list2를 정령한다.
print(list1,list2);
// 결과 : list1 :[0, 1, 2, 3, 4, 5]
System.out.println("list1.containsAll(list2):"+list1.containsAll(list2)); // list1이 list2를 포함하고 있는가
// true 출력
list2.add("B");
list2.add("C");
list2.add(3,"A"); // 원하는 자리에 값을 넣을 수 있음(그 뒤에 값들은 한칸씩 밀림)
print(list1,list2);
// 결과 : list1 :[0, 1, 2, 3, 4, 5]
// list2 :[4, 2, 0, A, B, C]
list2.set(3,"AA"); // 값 변경
print(list1,list2);
// list2 :[4, 2, 0, AA, B, C]
list1.add(0,"1"); // 현재 ArrayList배열안 값 = ["1",0,1,2,3,4,5] index[0]번과 index[2]번의 1은 다름
System.out.println("index =" + list1.indexOf("1"));
System.out.println("index =" + list1.indexOf(1));
print(list1,list2);
// 결과 : index = 0
// index = 2
list1.remove(0); // [0,1,2,3,4,5] index를 통한 자리값 삭제
list1.remove(new Integer(1)); // [0,2,3,4,5] // 객체를 통한 값 삭제
print(list1,list2);
}
static void print(ArrayList list1, ArrayList list2){
System.out.println("list1 :"+list1);
System.out.println("list2 :"+list2);
System.out.println();
}
}
ArrayList에 저장된 객체(index(2))의 삭제 과정
(1) index(2)보다 아래에 있는 index의 값을 한칸씩 위로 올려 덮어 씌움 index(3), index(4)를 한칸씩 위로 덮어씌움
(2) 그럼 기존에 index(4)에 남아있는 값이 있을텐데 이 값을 null로 바꿈
(3) 그 후 원래 인덱스 값이 5였는데 그값을 -1하여 4로 줄임
(4) 따라서 for문 사용하여 여러개의 값을 지울때는 0부터가 아닌 맨 아래부터 진행해야 빠르고 깔끔하게 삭제됨
for(int i =list.size()-1; i>=0; i--){
list.remove(i);
}
※ 객체 삽입과정은 이와 반대로 진행
(1) 일반 LinkedList
class Node{
Node next; // 다음 노드 주소 ex) 0x300
Object obj // 자신의 값 0
}
(2) 이중 LinkedList
class Node{
Node next; // 다음 노드 주소
Node previous; // 이전 노드 주소
Object obj; // 현재 값
}
(3) 원형 연결 리스트
(1) 순차적으로 데이터를 추가/삭제 = ArrayList 빠름
(2) 비순차적으로 데이터를 추가/삭제 = LinkedList 빠름
(3) 접근시간 = ArrayList 빠름
HashSet<Integer> set = new HashSet<Integer>(); // HashSet 초기화
set.add(1); // HashSet 값 추가
set.add(2);
set.remove(1); // HashSet 값 1 삭제(HashSet은 인덱스가 없기 때문에 값이 사라짐(1 삭제)
set.size(); // 사이즈 구함 (사이즈 : 1)
set.clear(); // 전부 삭제
HashSet와 LinkedHashSet 차이점
- HashSet은 중복을 제거해준다는 장점이 있지만 저장 순서를 지켜주지 않음 예를 들어 [1,2,3,4]를 넣고 싶어 1부터 4까지 순서대로 set에 넣을때 set에는 1부터 4까지 순서대로 저장이 되지 않을 수 있다.
- 따라서 이를 보완하고자 사용하는 것이 LinkedHashSet으로 입력받는 순서대로 저장시켜준다.
(1) 실습1. 중복 데이터 판별
import java.util.HashSet;
import java.util.Set;
public class SetExercise {
public static void main(String[] args) {
Set<String> set1 = new HashSet<>();
set1.add("김경록");
set1.add("김경록"); //중복으로 들어가지 않음
Set<Integer> setInteger = new HashSet<>();
setInteger.add(1);
setInteger.add(1); // 중복으로 들어가지 않음
setInteger.add(2);
setInteger.add(2); // 중복으로 들어가지 않음
System.out.println(setInteger);
}
}
(2) 실습2. 임의의 숫자 50개 생성수 중복 제거
- 숫자 생성을 위한 인터페이스
public interface NumberGenerator {
int generate(int num); //숫자를 생성하는 메소드
}
- 숫자 생성을 위한 인터페이스 상속
public class RandomNuberGenerator implements NumberGenerator{
@Override
public int generate(int num) {
return (int)(Math.random()*num);
//num 미만의 랜덤한 숫자를 생성하여 리턴한다.
}
}
- 메인 메서드
import java.util.HashSet;
import java.util.Set;
public class RndNumbersWithoutDuplicated {
public static void main(String[] args) {
RandomNuberGenerator randomNuberGenerator = new RandomNuberGenerator();
HashSet<Integer> numbers = new HashSet<>();
for(int i=0;i<50;i++){
int r= randomNuberGenerator.generate(10);
numbers.add(r); //값이 중복된다면 또다시 저장하지 않는다.
}
System.out.println(numbers);
System.out.println(numbers.size());
}
}
(3) 실습3. A~Z중 임의의 알파벳을 50개 생성후 중복 제거
- 인터페이스
public interface Generator {
char generate();
}
- 인터페이스 상속
public class AlphabetGenerator implements Generator {
@Override
public char generate() {
char c = (char) ( Math.random()*26+65);
return c;
}
}
- 메인 메서드
import java.util.HashSet;
public class RandomAlphabet {
public static void main(String[] args) {
AlphabetGenerator alphabetGenerator = new AlphabetGenerator();
HashSet<Character> alphabets = new HashSet<>();
for(int i=0;i<50;i++){
char r= alphabetGenerator.generate();
alphabets.add(r);
}
System.out.println(alphabets);
System.out.println(alphabets.size());
}
}
(4) 실습4. 다른 클래스의 통한 값 추가
import java.util.HashSet;
import java.util.Objects;
class Person{
String name;
int age;
// 비교를 위한 오버라이딩
@Override
public boolean equals(Object o) {
if(!(o instanceof Person)) return false;
Person person = (Person) o;
// 나 자신(this)의 이름과 나이를 p와 비교
return this.name.equals(person.name) && this.age == person.age;
}
@Override
public int hashCode() {
return Objects.hash(name, age); // 클래스의 인스턴스 변수를 전부 넣어줌
}
// --- 오버라이딩 여기까지 ---
Person(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return name+" : "+age;
}
}
public class HashSetTest {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add("abc");
set.add("abc");
// 객체를 생성하여 Set안에 넣을때는 객체의 주소가 다르기 때문에 같은 내용이 중복되서 들어감
// 따라서 이를 방지하기 위해 객체의 클래스 안에서 hashcode와 equals를 통해 오버라이딩을 해줘 중복방지를 함
set.add(new Person("David",10));
set.add(new Person("David",10));
System.out.println(set);
}
}
기본 예제
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
Set set = new TreeSet(); // 따로 정렬해줄 필요 없음
for(int i =0; set.size()<6; i++){
int num = (int)(Math.random()*45)+1;
set.add(num);
}
System.out.println(set);
}
}
--- 결과 ---
[5, 8, 20, 35, 38, 42]
범위 검색 예제
import java.util.TreeSet;
public class TreeSetTest2 {
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));
System.out.println("40과 80사이의 값 :"+set.subSet(40,80));
}
}
--- 결과 ---
50보다도 작은 값 :[10, 35, 45]
50보다도 큰 값 :[50, 65, 80, 95, 100]
40과 80사이의 값 :[45, 50, 65]
Map(String, Integer> map = new HashMap<>(); // HashMap<타입,타입> 선언
map.put("홍길동",1); // map에 값 넣기(key,value) {홍길동=1}
map.put("이순신",2); // {이순신=2}
map.remove("홍길동"); // 홍길동이란 키값을 가진 데이터 삭제
map.size(); // 1
(1) 실습1. 입력받은 문자열중 알파벳 개수 세기
import java.util.HashMap;
import java.util.Map;
public class AlphabetCnt {
public static void main(String[] args) {
String s1 = "abbccceefgh";
String upper = s1.toUpperCase(); // 모든 문자 대문자로 변환
Map<Character,Integer> map = new HashMap<>();
for(char c = 'A'; c<='Z'; c++){ // A~Z까지 비교
int count = 0;
for(int i=0; i<upper.length(); i++){
char s = upper.charAt(i); // 입력한 문자열 문자로 변환
if(isAlphabet(s)){ // 입력받은 문자가 알파벳이라면
if(c == s){ // 현재 바깥 for문에서 A문자를 돌리는 중일때
count++; // A문자와 입력받은 문자가 같을때 카운트
}
}
}
map.put(c,count);
}
System.out.println(map);
}
public static boolean isAlphabet(char c){
return ('A'<= c && c<='Z');
}
}
(2) 로그인 예제
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class HashMapTest {
public static void main(String[] args) {
Map<String,String> map = new HashMap();
map.put("abc","1234");
map.put("hello","5678");
map.put("abc","123"); // 기존의 데이터 덮어 씌움
Scanner scan = new Scanner(System.in);
while(true){
System.out.println("id와 pw를 입력해주세요.");
System.out.print("id :");
String id = scan.nextLine().trim(); // 공백을 제거해줌 "1234 " => "1234"
if(!map.containsKey(id)){ // 입력받은 id가 map에 저장되어 있는 키와 다를때
System.out.println("입력한 id는 존재하지 않습니다.");
continue; // while문 처음으로 이동
}
System.out.print("pw :");
String pw = scan.nextLine().trim();
if(!(map.get(id).equals(pw))){
System.out.println("비밀번화가 일치하지 않습니다. 다시 입력해주세요:");
}else{
System.out.println("로그인되었습니다.");
break;
}
}
}
}
static Collection synchronuzedCollection(Collection c)
static List synchronuzedList(List list)
static Set synchronuzedSet(Set set)
static Map synchronuzedMap(Map map)
static SortedSet synchronuzedSortedSet(SortedSet s)
--
List syncList = Collections.synchronuzedList(new ArrayList(...));
(동기화된 리스트) (동기화되지 않은 리스트)
static Collection unmodifiableCollection(Collection c)
static List unmodifiableList(List list)
static Set unmodifiableSet(Set set)
static Map unmodifiableMap(Map map)
static NavigableSet unmodifiableSortedSet(NavigableSet s)
static SortedSet unmodifiableMap(SortedSet s)
static NavigableMap unmodifiableMap(NavigableMap m)
static SortedMap unmodifiableMap(SortedMap m)
static List singleTonList(Object o)
static Set singleTon(Object o) // singleTonSet 아님
static Map singleTonMap(Object key,Object value)
static Collection checkedCollection(Collection c, Class type)
static List checkedList(List list, Class type)
static Set checkedSet(Set set, Class type)
static Map checkedMap(Map map, Class keytype, Class valuetype)
Collections 메서드 실습
List list = new ArrayList<>();
System.out.println(list);
// 리스트에 값 대입
addAll(list,1,2,3,4,5); // 원래는 Collections.addAll()인데 import를 통해 Collections.* 하여 생략가능
System.out.println(list); // [1,2,3,4,5]
// 오른쪽으로 값 2번 이동
rotate(list,2); // [1,2,3,4,5] -> [5,1,2,3,4] -> [4,5,1,2,3]
// 0번째와 2번째 자리 값 변경
swap(list,0,2); // [1,5,4,2,3]
// 랜덤으로 자리 섞음
shuffle(list); // [2,4,5,1,3]
// 역순으로 정렬
sort(list,reverseOrder()); // [5,4,3,2,1]
sort(list); // [1,2,3,4,5]
int idx = binarySearch(list,3); // 3이 저장된 인덱스값 반환 idx=2
// 최대,최소값 구하기
max(list); // 5
min(list); // 1
max(list,reverseOrder()); // 뒤에서 제일 큰값 1 (min과 같음)
fill(list,9); // 전부 9로 채움 [9,9,9,9,9]
// list와 같은 크기의 새로운 list를 생성하고 2로 채운다. 단, 결과는 변경불가
List newlist = nCopies(list.size(),2); // [2,2,2,2,2]
// 2개를 비교하여 공통요소가 없으면 true 출력
disjoint(list,newlist); // true
copy(list,newlist); // list안의 값에 newlist값을 복사해서 대입
disjoint(list,newlist); // false
replaceAll(list,2,1); // list안 2의 값을 1로 바꿈 [1,1,1,1,1]