본문 바로가기

Programming/Java

List

잠시 혼자서 안드로이드 개발을 하면서 자바를 만지는 중인데, 애초에 사용했던 언어가 C++ 이다 보니까, vector를 대체 할 것을 찾던 중 List에 대해서 확인하게 되었다. List에 몇가지 종류가 있기는 하는데 디테일 한것은 나중에 하기로 하고, LinkedList 라는 클래스의 실제 사용에 대해서만 포스트 남겨 본다.

  

List들이 가질 수 있는 것들은 기본 타입(int, double, ...)은 들어 갈 수 없고, 불특정 Object만 들어가게 된다. 원래 테스트로 int 를 하려고 보니까, 안되서 Integer로 테스트ㅋ 각기 테스트는 Integer, String, 자체 클래스로 하였다.

  

일단 각각의 List를 예쁘게 출력하게끔 만들어는 봤는데... 한꺼번에 합치는 건 잘 모르겠다.

  

private static void printIntegerList(List<integer> l)
{
	System.out.println("list Size : "+l.size());
	for(Object i : l)
	{
		System.out.print(i + " ");
	}
	System.out.println("\n");
}

private static void printStringList(List<String> l)
{
	System.out.println("list Size : "+l.size());
	for(Object i : l)
	{
		System.out.print(i + " ");
	}
	System.out.println("\n");
}

private static void printMyList(List l)
{
	System.out.println("list size : "+l.size());
	for(Object i : l)
	{
		System.out.print(i+" ");
	}
	System.out.println("\n");
}

  

보시면 알겠지만 내부는 다 똑같다. 근대 어떻게 하나의 함수명으로 하는 지 사용법을 영.....;;;

  

뭐 딱히 중요 한 것은 아니니까 넘어가고...

List<Integer>의 사용법 이다. 아래와 같이 선언하고 사용하면 된다.

List<Integer> listIntegerTest = new LinkedList<Integer>();

  

C++에서 vector의 넣는 함수처럼 원소 삽입은 add(Object o) 메쏘드를 사용 하면 된다. 아래는 14부터 5까지 차례로 원소로 넣어 보았다.

for(Integer i = 14 ; i >= 5 ; --i)
{
	listIntegerTest.add(i);
}

  

제거는 인덱스로 제거 할 수도 있으며 해당 Object로 제거 할 수도 있다. remove(int idx) 또는 remove(Object o)메쏘드를 사용 하면 된다.

0번째 인덱스를 제거해 보았다.

listIntegerTest.remove(0);		// 14제거

  

remove(..) 함수는 제거되는 인덱스의 원소를 반환한다. 한번 더 0 번째 인덱스를 제거해 보았다. 기존에 14부터 5까지 넣었는데 0번째 인덱스를 두 번째 제거하는 것이므로 13원소가 제거 된다.

// remove 함수는 제거되는 인덱스의 원소를 반환한다.
System.out.println("removed element : " + listIntegerTest.remove(0));		// 2제거

  

하지만 인덱스를 벗어나게 되면 예외처리를 발생시키게 된다. 지금의 예시는 Integer로 하게 되는데, 앞서 add(..)시에는 바로 int가 Integer로 자동 캐스트가 되지만, remove는 두 가지 타입(인덱스 접근시 int, 오브젝트 접근시 Integer의 메쏘드가 별도로 있으므로 벗어나는 인덱스에서는 예외처리를 던지게 된다.

try
{
	// 인덱스를 벗어 났을 경우
	// 근대 이게 사실 Interger 10을 제거 하고 싶은 거라면?
	listIntegerTest.remove(10);
}
catch(Exception e)
{
	// IndexOutOfBoundsException을 알려주며, 제거 인덱스와 현재 Size를 알려준다.
	System.out.println(e);
}

  

Object로 원소를 삭제 할 경우에는 boolean 값을 반환한다. 있어서 삭제가 되었다면 true, 없거나 실패했으면 false를 반환(하는데 사실 실패 할 경우는 잘 모르겠다ㅋ)한다.

System.out.println("remove \"10\" object after made Integer \"10\" object");
Integer ten = 10;
System.out.println("ten object revmoed success ? " + listIntegerTest.remove(ten));
System.out.println("ten object revmoed success ? " + listIntegerTest.remove(ten));

  

String 클래스는 문자열에 대한 클래스 이다. 더블쿼터스(")로 묶여있는 문자의 집합이며 무조건 String 객체로 자동 캐스트 시켜주는 듯 싶다.

아래는 List<String> 생성후 "a"부터 "j"까지 순서대로 넣어 보았다.

List<String>	listStringTest = new LinkedList<String>();

listStringTest.add("a");
listStringTest.add("b");
listStringTest.add("c");
listStringTest.add("d");
listStringTest.add("e");
listStringTest.add("f");
listStringTest.add("g");
listStringTest.add("h");
listStringTest.add("i");
listStringTest.add("j");

  

삭제 부분은 위와 같으므로 일단은 단순 제거 해 보았다.

System.out.println("remove 0th index & \"b\" object...");
listStringTest.remove(0);		// 인덱스 제거
listStringTest.remove("b");		// 오브젝트 제거

  

이러한 특정 원소들의 집합체를 사용하는 가장 큰 이유 중에 하나는 정렬! C++의 STL처럼(사실 이런건 자바가 먼저 만든 것으로 알고 있지만 여튼 전 C++유저니까ㅋ) 너무나도 잘 되어있다. 이러한 집합체를 다루는 Collections가 가지고 있는 메쏘드를 가지고 정렬을 할 수 있다.

  

기본적으로 두가지 방법이 존재 한다. Collections.sort(List<T> l)과 Collections.sort(List<T> l, Comparator <? Super T> c). 전자는 해당 클래스가 가지고 있는 compareTo 라는 메쏘드가 이미 선언이 되어 있는 상태에서 기본적인 오름차순 정렬을 해준다. 후자는 각 클래스가 가지고 있는 맴버변수별로 따로 정렬 방식을 달리 해줘야 할 때 사용 된다. 일단 기본적인 오름차순을 가지고 내림차순으로 바꾸는 정렬은 밑에서 바로 보여주겠다.

Collections.sort(listIntegerTest);		// 기본적으로는 오름차순 정렬
printIntegerList(listIntegerTest);		// 출력 확인

  

Collections가 가진 메쏘드 중에 reverse(..) 메쏘드는 List와 같이 순서가 존재하는 집합체를 역으로 설정한다. 오름차순으로 정렬한 후에 거꾸로 하게 되면 자동으로 내림차순!

Collections.reverse(listIntegerTest);	// 거꾸로 저장
printIntegerList(listIntegerTest);		// 출력 확인

  

String Class도 마찮가지 방법으로 해 보았다.

Collections.sort(listStringTest);		// 기본적으로는 오름차순 정렬
printStringList(listStringTest);		// 출력 확인

Collections.reverse(listStringTest);	// 거꾸로 저장
printStringList(listStringTest);		// 출력 확인

  

이제 직접 define한 클래스에 대해서 접근해 보자. 사실 이번에 가계부 어플을 만들기 이전에 Java에 대해서도 어느정도 필요한 기본만 슬쩍 보려고 한 것이 이렇게 포스트가 길어졌지만, 나중에 다시 볼 생각 하면서 작성해 보았다.

  

myDetailCategoryTest 에 대한 클래스는 아래와 같다. Index는 그냥 유니크한 킷값이고 중요한 건 Count이다. 각기 다른 Count에 대해서 정렬이 되어야 하기 때문에 일단은 이것만 두었다. 실제로는 다른 변수들이 여럿 더 있지만 그냥 객체 집합체의 정렬을 테스트 해보려고 만들었다.(하지만 하나의 변수만을 가지고 정렬 할 수도 있으니까 기본 정렬 방식에 대한 부분도 같이 언급)해당 클래스를 만들 때 비교가능한 클래스라고 선언 해주고 해당 메소드인 compareTo(해당클래스 o); 를 구현해주면 된다.(아마 이클립스를 사용하면 빨간줄이 그어지고(클래스 명에) 그곳에 마우스를 올리면 만드는게 나올 듯 싶다.

public class myDetailCategoryTest implements Comparable<myDetailCategoryTest>{
	private Integer		m_Index;
	private Integer		m_Count;
		
	public myDetailCategoryTest(Integer index, Integer count)
	{
		// 초기화
		m_Index 		= index;
		m_Count 		= count;
	}
	
	public Integer getCount(){ return m_Count; }
	public Integer getIndex(){ return m_Index;	}
	
	public String toString()
	{
		return m_Index + "(" + m_Count + ")";
	}
	
	public int compareTo(myDetailCategoryTest other)
	{
		if(m_Count > other.getCount())
			return 1;
		else if(m_Count < other.getCount())
			return -1;
		else
			return 0;
	}
}

  

하나의 변수만 있을 땐, 실상 이렇게 자세하게 구현할 필요는 없지만, 실제로는 변수가 많으므로 Comparator라는 인터페이스를 구현해야 한다. 이 Comparator는 기본적인 함수로 compare를 생성하게 되는데 이때 필요한 것이 어떤 클래스를 비교하게 되는지 알아야 하기 때문에 초기에 알려줘야 한다.

import java.util.Comparator;

public class CompareMyClassCountASC implements Comparator<myDetailCategoryTest>{
	public int compare(myDetailCategoryTest o1, myDetailCategoryTest o2) {
		// Compare 함수를 Collections.sort(..)의 두번째 인자로 넣어준다.
		
		// 기본적으로 이 설정은 오름차순 정렬
		if(o1.getCount() > o2.getCount())
			return 1;
		else if(o1.getCount() < o2.getCount())
			return -1;
		else
			return 0;
		
		// 애초에 내림차순 정렬을 하고 싶으면 메쏘드를 새로 만들어서
		// Collections.sort(..)의 두번째 인자로 넣어주던지,
		// 현재 이 메쏘드로 정렬을 한후에 Collectors.reverse(..)로 거꾸로 저장 하면 된다.
		// 두가지 방법 모두 사용 해 보겠다.
	}
}

  

내림차순 정렬도 따로 만들어 보았다. 실제로는 오름차순하고 reverse 한 것과 별 차이는 없다.

import java.util.Comparator;

public class CompareMyClassCountDESC implements Comparator<myDetailCategoryTest>{
	public int compare(myDetailCategoryTest o1, myDetailCategoryTest o2)
	{
		// 내림차순 정렬
		if(o1.getCount() > o2.getCount())
			return -1;
		else if(o1.getCount() < o2.getCount())
			return 1;
		else
			return 0;
	}
}

  

일단 모두다 Comparator를 구현한 클래스로 정렬 한 후 출력한 결과이다.

// 오름차순 정렬(별도 비교 클래스 사용)
Collections.sort(listMyTest, new CompareMyClassCountASC());
printMyList(listMyTest);

// 내림차순 정렬(별도 비교 클래스 사용)
Collections.sort(listMyTest, new CompareMyClassCountDESC());
printMyList(listMyTest);

  

기본 구현한 비교 함수를 통한 정렬과 reverse를 통한 재배치를 한 후 출력한 결과이다.

Collections.sort(listMyTest2);
printMyList(listMyTest2);

// 원소 역으로 재배치
Collections.reverse(listMyTest2);
printMyList(listMyTest2);

  

이제... 전체 코드 다 합쳐서 이런 모양이 된다. 그냥 사용만 하는 다른 분들도 도움을 받았으면 한다.

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class main {

	public static void main(String[] args) {
		/****************************************************
		 * 기본적인 사용 방법
		******************************************************/
		//**** Interger Object 사용시 ****/
		List<Integer> listIntegerTest = new LinkedList<Integer>();
		
		// listTestObject 에 1부터 10까지 넣는다.(add)
		for(Integer i = 14 ; i >= 5 ; --i)
		{
			listIntegerTest.add(i);
		}
		
		// 전체 출력 확인
		printIntegerList(listIntegerTest);
		
		// 인덱스로 제거
		System.out.println("0th index remove...");
		listIntegerTest.remove(0);		// 14제거
		
		// remove 함수는 제거되는 인덱스의 원소를 반환한다.
		System.out.println("removed element : " + listIntegerTest.remove(0));		// 2제거
		
		// 전체 출력 확인
		printIntegerList(listIntegerTest);
		
		System.out.println("Fire Exception!!!");
		try
		{
			// 인덱스를 벗어 났을 경우
			// 근대 이게 사실 Interger 10을 제거 하고 싶은 거라면?
			listIntegerTest.remove(10);
		}
		catch(Exception e)
		{
			// IndexOutOfBoundsException을 알려주며, 제거 인덱스와 현재 Size를 알려준다.
			System.out.println(e);
		}
		
		// remove는 boolean을 반환한다.
		// Integer 10 객체를 만들어서 삭제
		System.out.println("remove \"10\" object after made Integer \"10\" object");
		Integer ten = 10;
		System.out.println("ten object revmoed success ? " + listIntegerTest.remove(ten));
		System.out.println("ten object revmoed success ? " + listIntegerTest.remove(ten));
		
		// 전체 출력 확인
		printIntegerList(listIntegerTest);
		
		
		//**** String Class 사용시 ****//
		List<String>	listStringTest = new LinkedList<String>();
		
		listStringTest.add("a");
		listStringTest.add("b");
		listStringTest.add("c");
		listStringTest.add("d");
		listStringTest.add("e");
		listStringTest.add("f");
		listStringTest.add("g");
		listStringTest.add("h");
		listStringTest.add("i");
		listStringTest.add("j");
		
		// 전체 출력 확인
		printStringList(listStringTest);
		
		// 제거
		System.out.println("remove 0th index & \"b\" object...");
		listStringTest.remove(0);		// 인덱스 제거
		listStringTest.remove("b");		// 오브젝트 제거
		
		// 전체 출력 확인
		printStringList(listStringTest);
		
		
		/****************************************************
		 * 기존에 이미 정의 되어 있는 객체의 정렬
		******************************************************/
		// Integer Object 정렬
		System.out.println("Integer object list sort & print...");
		Collections.sort(listIntegerTest);		// 기본적으로는 오름차순 정렬
		printIntegerList(listIntegerTest);		// 출력 확인
		
		Collections.reverse(listIntegerTest);	// 거꾸로 저장
		printIntegerList(listIntegerTest);		// 출력 확인
		
		// String Object 정렬
		System.out.println("String object list sort & print...");
		Collections.sort(listStringTest);		// 기본적으로는 오름차순 정렬
		printStringList(listStringTest);		// 출력 확인
		
		Collections.reverse(listStringTest);	// 거꾸로 저장
		printStringList(listStringTest);		// 출력 확인
		
		/****************************************************
		 * 사용자 지정 클래스 사용
		******************************************************/
		List<myDetailCategoryTest> listMyTest  = new LinkedList<myDetailCategoryTest>();
		List<myDetailCategoryTest> listMyTest2 = new LinkedList<myDetailCategoryTest>();
		Random oRandom = new Random();
		
		for(int i = 1 ; i <= 10 ; ++i)
		{
			myDetailCategoryTest elem = new myDetailCategoryTest(i, oRandom.nextInt(10)+1);
			listMyTest .add(elem);
			listMyTest2.add(elem);
		}
		
		System.out.println("When use implements class method...");
		printMyList(listMyTest);
		
		// 오름차순 정렬(별도 비교 클래스 사용)
		Collections.sort(listMyTest, new CompareMyClassCountASC());
		printMyList(listMyTest);
		
		// 내림차순 정렬(별도 비교 클래스 사용)
		Collections.sort(listMyTest, new CompareMyClassCountDESC());
		printMyList(listMyTest);
		
		// 오름차순 정렬
		System.out.println("When use default method...");
		printMyList(listMyTest2);
		
		Collections.sort(listMyTest2);
		printMyList(listMyTest2);
		
		// 원소 역으로 재배치
		Collections.reverse(listMyTest2);
		printMyList(listMyTest2);
	}
	
		
	private static void printIntegerList(List<Integer> l)
	{
		System.out.println("list Size : "+l.size());
		for(Object i : l)
		{
			System.out.print(i + " ");
		}
		System.out.println("\n");
	}
	
	private static void printStringList(List<String> l)
	{
		System.out.println("list Size : "+l.size());
		for(Object i : l)
		{
			System.out.print(i + " ");
		}
		System.out.println("\n");
	}
	
	private static void printMyList(List<myDetailCategoryTest> l)
	{
		System.out.println("list size : "+l.size());
		for(Object i : l)
		{
			System.out.print(i+" ");
		}
		System.out.println("\n");
	}

}
>

'Programming > Java' 카테고리의 다른 글

난수 사용 하기  (0) 2012.07.24