본문 바로가기
PROGRAMING📚/Java📑

Java::활용 - List

Ta이니 2024. 7. 5.
728x90
반응형

배열과 collection

 

배열의 장점과 단점은 

장점 : 복수의 데이터를 하나의 이름으로 처리(index 접근)

단점 : 배열의 크기 조정 불가하고 타입이 고정적이다 

 

하지만 collection은 size가 가변적이고 타입에 자유롭기 때문에

리스트를 사용하면 자료 추가와 수정이 용이하다

 

종류: List(순서 O,중복 O), Set(순서 X, 중복 X) ,

Map(순서{key:X, value: X}/중복{key: X value: O}) + Hash, Tree

 

List

 

특징: 순서가 있고, 중복이 가능하다

 

Member라는 클래스를 생성하여 List 안에 Member를 추가해주려고 한다

class Member{
  private String id;
  private String pass;
  private String name;
  public Member(String id, String pass, String name) {
    this.id = id;
    this.pass = pass;
    this.name = name;
  }
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getPass() {
    return pass;
  }
  public void setPass(String pass) {
    this.pass = pass;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  //Ctrl+o 사용하면 자동생성 가능
  @Override
  public String toString() {
    return String.format("%s(ID : %s)",name,id);
  }

메인 메소드에서 List list = new ArrayList()를 생성해서

새로운 리스트를 하나 만들어준다

public class Ex01List {
  public static void main(String[] args) {
    List list = new ArrayList();
    ist<Member> list2 = new ArrayList(); //Member type 만 받음 :: 제네릭스
    
    list.add(new Member("hgd","1","홍길동"));
    list.add(new Member("kgd","2","김길동"));
    list.add(new Member("jgd","3","정길동"));
  }
}

다음과 같이 리스트안에 쉽게 값을 추가 하는 것이 가능함

list를 출력하는 방법

System.out.println(list);

list 안의 특정 원소를 출력하는 방법

System.out.println(list.get(0));

 

ArrayList()와 LinkedList() 의 차이

 

ArrayList와 LinkedList는 Java의 List 인터페이스를 구현한 두 가지 주요 클래스입니다.

이 둘은 데이터를 저장하고 관리하는 방식이 다르며, 각기 다른 성능 특성과 사용 사례를 가집니다

더보기

1. 데이터 저장 방식

  • ArrayList:
    • 내부적으로 배열을 사용하여 데이터를 저장합니다.
    • 인덱스를 통해 요소에 접근할 수 있습니다.
    • 배열의 크기를 동적으로 조절할 수 있지만, 크기를 늘릴 때는 새로운 배열을 생성하고 기존 요소를 복사하는 작업이 필요합니다.
  • LinkedList:
    • 이중 연결 리스트(doubly linked list) 구조를 사용합니다.
    • 각 요소는 노드로 표현되며, 노드는 데이터와 다음 및 이전 노드에 대한 참조를 포함합니다.
    • 요소 접근은 노드를 따라 순차적으로 이루어집니다.

2. 성능 차이

  • 접근 시간:
    • ArrayList: 인덱스를 통해 상수 시간 O(1)에 요소에 접근할 수 있습니다.
    • LinkedList: 인덱스로 접근할 때는 첫 번째 노드부터 순차적으로 접근해야 하므로 평균적으로 O(n/2) 시간이 소요됩니다. 최악의 경우 O(n) 시간이 소요됩니다.
  • 삽입 및 삭제 시간:
    • ArrayList:
      • 요소를 배열의 끝에 추가하는 것은 평균적으로 상수 시간 O(1)이지만, 배열의 크기를 늘려야 하는 경우 O(n) 시간이 걸릴 수 있습니다.
      • 중간에 요소를 삽입하거나 삭제하는 경우, 배열의 나머지 요소를 이동시켜야 하므로 O(n) 시간이 소요됩니다.
    • LinkedList:
      • 첫 번째나 마지막 요소를 추가하거나 삭제하는 것은 상수 시간 O(1)에 수행됩니다.
      • 중간 요소의 삽입이나 삭제도 해당 위치까지 순차적으로 접근하는 시간 O(n)과 함께 상수 시간 O(1)로 수행됩니다.

3. 메모리 사용

  • ArrayList:
    • 요소만을 저장하며, 추가적인 객체나 참조를 저장하지 않습니다.
    • 크기를 조절할 때 새로운 배열을 생성하고 기존 요소를 복사해야 하므로 일시적으로 더 많은 메모리를 사용할 수 있습니다.
  • LinkedList:
    • 각 요소가 데이터와 함께 두 개의 참조(다음 노드와 이전 노드)를 저장해야 하므로, 추가적인 메모리 오버헤드가 있습니다.

4. 기타 기능

  • ArrayList:
    • RandomAccess 인터페이스를 구현하여, 임의 접근이 빠릅니다.
    • Serializable과 Cloneable 인터페이스를 구현합니다.
  • LinkedList:
    • Deque 인터페이스를 구현하여, 큐(queue) 및 덱(deque)로 사용될 수 있습니다.
    • Serializable과 Cloneable 인터페이스를 구현합니다.

사용 예시

  • ArrayList:
    • 데이터를 자주 읽고 접근해야 하는 경우에 적합합니다. (예: 인덱스를 통해 요소를 빈번히 읽는 경우)
    • 배열의 크기를 미리 예측할 수 있는 경우에 유리합니다.
  • LinkedList:
    • 삽입과 삭제가 빈번히 발생하는 경우에 적합합니다. (예: 큐, 스택, 덱 구현)
    • 요소의 순차적인 접근이 주로 이루어지는 경우에 유리합니다.
List linkedList = new LinkedList();

 

  • **ArrayList**는 빠른 임의 접근이 필요한 경우에 유리하며, 데이터의 크기가 자주 변하지 않을 때 적합합니다.
  • **LinkedList**는 빈번한 삽입과 삭제 작업이 필요할 때 유리하며, 큐나 스택과 같은 자료 구조를 구현할 때 적합합니다.

 

for문을 사용해서 리스트 출력하기 

public class Ex01List {
  public static void main(String[] args) {
    List list = new ArrayList();
    List<Member> list2 = new ArrayList(); //Member type 만 받음 :: 제네릭스
    list.add(new Member("hgd","1","홍길동"));
    list.add(new Member("kgd","2","김길동"));
    list.add(new Member("jgd","3","정길동"));
    System.out.println(list);
    //1.for index
    for (int i=0; i<list.size(); i++) {
      System.out.println(list.get(i));
      Utils.typeOf(list.get(i));
    }
    //2.enhanced for
    for(Object o : list){
      System.out.println(o);
      Utils.typeOf(o);
    }
  }
}

 

Iterator

Iterator it = list.iterator();
while (it.hasNext()){
    System.out.println(it.next());
}

Consumer

 

java.util.function 패키지에 속해 있다

Consumer는 입력 매개변수를 받아서 어떤 동작을 수행하지만,

결과를 반환하지 않는 함수형 인터페이스를 말한다

 

//03. foreach -1
//익명객체는 일회성이고 참조할 일이 없는 경우에 사용한다
list.forEach(new Consumer() {
      @Override
      public void accept(Object o) {
        System.out.println("forEach: "+o);
        Utils.typeOf(o);
      }
    });
//03. foreach -2 , 람다식
list.forEach(o->{
    System.out.println("람다식: "+o);
    Utils.typeOf(o); });
//03. foreach -3
//클래스를 생성해야하는 경우, 참조 할 경우가 있을 경우
  class ObjConsumer implements Consumer{
      String lists="";
      @Override
      public void accept(Object o) {
        list+=o;
        System.out.println("forEach: "+o);
        Utils.typeOf(o);
      }
    }
    ObjConsumer oc = new ObjConsumer();
    list.forEach(oc); //list.forEach(Consumer consumer)
    System.out.println(oc.lists);
  }

 

데이터 리스트 삭제하기

list.clear();

리스트 안에 포함되어있는지 확인하는 방법 list.contains()

System.out.println( list.contains(10));

 

list.addAll(new ArrayList(5));

 

리스트가 비어있는지 확인하기

System.out.println(list.isEmpty());

 

 

ArrayList 처리시간 과 LinkedList 처리시간 확인하기

package p07_Collection;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Ex02LinkedList {
  public static void main(String[] args) {
    List al = new ArrayList();
    List ll = new LinkedList();
    System.out.println("==== 순차적 추가 ====");
    System.out.println("ArrayList: "+addSequentially(al));
    System.out.println("LinkedList: "+addSequentially(ll));
    System.out.println("==== 중간에 추가 ====");
    System.out.println("ArrayList: "+addMiddle(al));
    System.out.println("LinkedList: "+addMiddle(ll));
    System.out.println("==== 중간 삭제 ====");
    System.out.println("ArrayList: "+removeMiddle(al));
    System.out.println("LinkedList: "+removeMiddle(ll));
    System.out.println("==== 순차 삭제 ====");
    System.out.println("ArrayList: "+removeSequentially(al));
    System.out.println("LinkedList: "+removeSequentially(ll));
  }
  private static long addSequentially(List list){
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
      list.add(i+"");
    }
    long end = System.currentTimeMillis();
    return end - start;
  }
  private static long addMiddle(List list){
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
      list.add(5000,i+"");
    }
    long end = System.currentTimeMillis();
    return end - start;
  }
  private static long removeSequentially(List<String> list){
    long start = System.currentTimeMillis();
    for (int i = list.size()-1; i >=0; i--) {
      list.remove(i);
    }
    long end = System.currentTimeMillis();
    return end - start;
  }
  private static long removeMiddle(List<String> list){
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
      list.remove(i);
    }
    long end = System.currentTimeMillis();
    return end - start;
  }

}


Arrays : Collection에 배열을 다루기 위해 추가된 클래스 

package p07_Collection;

import java.util.Arrays;

public class Ex03Arrays {
  public static void main(String[] args) {
    int[]arr ={0,1,2,3,4};
    int []arr2 = Arrays.copyOf(arr, arr.length);
    int []arr3 = Arrays.copyOfRange(arr, 2,4);
    System.out.println(Arrays.toString(arr));
    System.out.println(Arrays.toString(arr2));
    System.out.println(Arrays.toString(arr3));
    
  }
}

int []arr4 = new int[5];
Arrays.fill(arr4, 10);
System.out.println(Arrays.toString(arr4));

Arrays.setAll(arr4, new IntUnaryOperator() {
      @Override
      public int applyAsInt(int operand) {
        return (int)(Math.random()*5);
      }
    });

Arrays.sort(arr4);
System.out.println(Arrays.toString(arr4));

int idx = Arrays.binarySearch(arr4,2);
System.out.println(idx);

 

    int[][] arr20={{11,12},{21,22}};
    System.out.println(Arrays.toString(arr20));
    System.out.println(Arrays.deepToString(arr20));

 

//배열을 List로 변환
Integer [] arrInt1 =  new Integer[]{0,1,2,3};
List<Integer> list = new ArrayList<>(Arrays.asList(arrInt1));

//list를 배열로
Integer [] arrInt2 = list.toArray(new Integer[arrInt1.length]);
System.out.println(Arrays.toString(arrInt2));

Integer[]arrInt3 = list.stream().toArray(value -> new Integer[value]);
System.out.println(Arrays.toString(arrInt3));


Stack

public class Ex04StackQueue {
  public static void main(String[] args) {
    Stack stack = new Stack();
    stack.push(0);stack.push(1); stack.push(2);
    System.out.println(stack);
    System.out.println(stack.size());
    System.out.println(stack.contains(1));
  }
}

System.out.println(stack.pop());
System.out.println(stack);
System.out.println(stack.push(4));
System.out.println(stack);
System.out.println(stack.peek());
System.out.println(stack);

Queue q= new LinkedList();
q.offer("a"); q.offer("b"); q.offer("c");
System.out.println(q);
System.out.println(q.poll());
System.out.println(q.peek());
System.out.println(q);

Colloection - Vector

Collection 이전에 나온 버전(동기화 포함)

    Vector v = new Vector();
    v.add(0);
    v.add("a");
    v.add(true);
    Enumeration e = v.elements();
    while (e.hasMoreElements()){
      System.out.println(e.nextElement());
    }
    e = v.elements(); //다시 사용하려고 할 때
    Iterator it = v.iterator();
    while (it.hasNext()){
      System.out.println(it.next());
    }
    it = v.iterator();//다시 사용하려고 할 때


Set

 

Set 선언하는 방법과 특징은 Set은 순서와 중복이 없다

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Ex05Set {
  public static void main(String[] args) {
    Set set = new HashSet();
    set.add(4); set.add(4);
    set.add(2); set.add(3);
    System.out.println(set);
  }
}

 

set.add(1); set.remove(4);
System.out.println(set);

 

for (int i : set) {
  //unboxing
  System.out.println(i);
  Iterator it = set.iterator();
  while (it.hasNext()) System.out.println(it.next());
}

 

package p07_Collection;

import com.sun.security.jgss.GSSUtil;

import java.util.*;

public class Ex05Set {
  public static void main(String[] args) {
    Set<Integer> set = new HashSet(); //boxing
    set.add(4); set.add(4);
    set.add(2); set.add(3);
    System.out.println(set);
    set.add(1); set.remove(4);
    System.out.println("Set1: "+set);
    for (int i : set) {
      //unboxing
      System.out.println(i);
    }

    Iterator it = set.iterator();
    while (it.hasNext()) System.out.println(it.next());
    System.out.println("------------------");
    Lotto lotto = new Lotto();
    lotto.Start();
    System.out.println("------------------");
    Set<Integer> lotto2 = new HashSet<>();
    while(lotto2.size()<6){
      lotto2.add((int)(Math.random()*45)+1);
    }
    ArrayList list3 = new ArrayList(lotto2);
    Collections.sort(list3);
    System.out.println(list3);

    //정렬이 되어서 나옴
    Set<Integer> lotto3 = new TreeSet<>();
    while (lotto2.size() <6 ){
      lotto2.add((int)(Math.random()*45)+1);
    }
    System.out.println(lotto3);
  }
}

class Lotto{
  void Start(){
    Set<Integer> number = new HashSet();
    while(number.size()<7)
    {
      int randomNum = (int)(Math.random()*(42)+1);
      if(!number.contains(randomNum)){
        number.add(randomNum);
        if(number.size() == 7){
          System.out.printf("보너스 : %d \n",randomNum);
        }
        else{
          System.out.printf("당첨번호 : %d \n",randomNum);
        }
      }
    }
    System.out.println(number);
  }
}

 

package p07_Collection;
import java.util.HashSet;
import java.util.Set;

public class Ex06Setequals {
  public static void main(String[] args) {
  Set set = new HashSet();
  set.add(new Person("LGH", "user1"));
  set.add(new Person("LGH", "user1"));
    System.out.println(set);
  }
}
class Person{
  String name, id;
  public Person(String name, String id)
  {
    this.name=name;
    this.id =id;
  }
}

new 연산자에 의해서 Hash 주소값이 다르게 들어간다

이 같은 값이 들어가는 경우, 같은 hashCode로 취급해 주기 위해서 다음 hashCode를 비교해주어야 한다

class Person{
  String name, id;
  public Person(String name, String id)
  {
    this.name=name;
    this.id =id;
  }

  @Override
  public int hashCode() {
    return super.hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    if(obj instanceof Person) {
      Person p = (Person) obj;
      return name.equals(p.name)&&id.equals(p.id);
    }
    return false;
  }
}

 

instanceof는 객체가 특정 클래스 또는 인터페이스의 인스턴스인지

여부를 확인하기 위해 사용되는 연산자이다

@Override
public boolean equals(Object obj) {
  if(obj instanceof Person) {
    Person p = (Person) obj;
    return name.equals(p.name)&&id.equals(p.id);
  }
  return false;
}

 

instanceof를 사용하는 이유는 

더보기

1. 타입 검사

if (obj instanceof String) {
    // obj는 String 타입입니다.
}

2. 안전한 타입 캐스팅

if (obj instanceof String) {
    String str = (String) obj;
    // 이제 안전하게 str을 사용할 수 있습니다.
}

3. 다형성과 유연성

public void process(Object obj) {
    if (obj instanceof String) {
        // String 타입에 대한 처리
    } else if (obj instanceof Integer) {
        // Integer 타입에 대한 처리
    } else if (obj instanceof MyCustomClass) {
        // MyCustomClass 타입에 대한 처리
    }
}

4. 인터페이스 구현 확인

if (obj instanceof MyInterface) {
    MyInterface myInterface = (MyInterface) obj;
    // 이제 myInterface를 사용하여 인터페이스 메서드를 호출할 수 있습니다.
}

 


TreeSet 

TreeSet은 정렬되는 기능을 가지고 정렬될 수 있는 값들만 받는다 

class Ball implements Comparable {
  private int num;
   public Ball(int num) {
    this.num = num;
  }

  @Override
  public int compareTo(Object o) {
    if(o instanceof Ball){
      Ball b = (Ball)o;
      //뺄 때 0 같다. 음수 작다, 양수 크다
      return num-b.num; //순차 정렬
      //return -(num-b.num); //역정렬
    }
    return 0;
  }

  @Override
  public String toString() {
    return num+" ";
  }
}

메서드를 재정의 하고 다른 곳에서 사용하기 위해서 인터페이스화 해주어야 한다 

import java.util.TreeSet;

public class Ex07TreeSet {
  public static void main(String[] args) {
    TreeSet set = new TreeSet();
    set.add(new Ball(4));
    set.add(new Ball(1));
    set.add(new Ball(3));
    System.out.println(set);
  }
}

 

 


Map 

 

key값은 중복이 불가능하지만, value 값는 중복이 가능하다

import java.util.HashMap;
import java.util.Map;

public class Ex08Map {
  public static void main(String[] args) {
    Map map = new HashMap();
    map.put("admin","1");
    map.put("user","1");
    if(!map.containsKey("member"))
      map.put("member","1");
    System.out.println(map);
  }
}

 

기존 key 값이 있는 경우,

key 값이 중복될 경우에는 마지막에 들어온 값이 덮어 써짐

 

if(!map.containsKey("member"))
  map.put("member","1");
map.put("member","3");

Map map = new HashMap();

//1) key 와 value 를 동시에 접근
Iterator it = map.entrySet().iterator();
while (it.hasNext()){
  Map.Entry entry = (Map.Entry)it.next();
  System.out.printf("key : %s, value : %s \n" ,entry.getKey(), entry.getValue());
}

//2) key 로 접근 할때,
it = map.keySet().iterator();
while(it.hasNext()){
  String key = (String) it.next();
  String value = (String) map.get(key);
  System.out.printf("k : %s , v: %s \n",key, value);
}

//3) value로 접근 할 때,
it = map.values().iterator();
while(it.hasNext()){
  String value = (String)it.next();
  System.out.println(value);
}

Map 데이터 지우기

"admin" 이라는 키를 가진 데이터를 삭제

map.remove("admin");


HashMap / TreeMap

 

package p07_Collection;

import p05_Inherit.common.Utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class Ex09MapApplicate {
  private static Map phoneBook = new HashMap();

  public static void main(String[] args) {
    addPhone("친구", "김수한", "010-1111-1110");
    addPhone("친구", "김수둘", "010-1111-1111");
    addPhone("친구", "김수셋", "010-1111-1112");
    addPhone("친구", "김수넷", "010-1111-1113");
    addPhone("마트", "010-1111-1114");

    printBook(phoneBook);
  }

  private static void addPhone(String group, String name, String tel) {
    if(!phoneBook.containsKey(group)){
      phoneBook.put(group,new HashMap<>());
    }
    HashMap book = (HashMap) phoneBook.get(group);
    book.put(name, tel);
  }

  private static void addPhone(String name, String tel) {
    addPhone("기타", name, tel);
  }

  private static void printBook(Map map) {
    System.out.println(map);
    Iterator it = phoneBook.keySet().iterator();
    while (it.hasNext()){
      String group = (String)it.next();
      HashMap book = (HashMap) phoneBook.get(group);
      System.out.printf("[ %s ] %d 개\n" , group, book.size());
      Iterator subIt = book.entrySet().iterator();
      while (subIt.hasNext()){
         Map.Entry entry = (Map.Entry)subIt.next();
        //Utils.typeOf(entry);
        System.out.printf("[ %s ] %s \n",entry.getKey(), entry.getValue());
      }
    }

  }

}

 

 

728x90
반응형

'PROGRAMING📚 > Java📑' 카테고리의 다른 글

Java::활용 - Stream  (0) 2024.07.05
Java::Thread  (0) 2024.07.05
Java:: 입출력 Stream I/O  (0) 2024.06.27
Java :: 활용 -String  (0) 2024.06.25
Java::확장-extends(상속)  (0) 2024.06.25

댓글