2013년 12월 15일 일요일

1 : n(one to many) 관계의 데이터를 저장하는 자료구조

package util;

 

public interface IDataStore {

 

public int on(String $type, String $value);

public void off(String $type, Object $object);

public void off(String $type, int $id);

public void off(String $type);

public void off();

public void trigger(String $type, Object $object);

public void trigger(String $type);

 

}

 

 

 

어떤 특정한 스트링키에 매핑시킬 수 있는 여러 데이터를 가질 수 있는 자료구조예요.

상황에 따라 키가 스트링이 아닌 오브젝트로 바꿔서 사용해도 됩니다. 그럼 더욱 더 넓은 관계의 데이터 구조를 다룰 수 있게 되겠죠. 값이 아닌 키조차도 오브젝트형이라면.

 

내부적으론 자바의 Map과 배열리스트라는 자료를 응용해서 만든거구요.

 

C++의 STL을 사용하면 자바보다 훨씬 쉽게 구현할 수 있어요. STL은 구조체의 성격이라서 얼록이라는 과정이 필요없고 이 부분은 이런 자료구조의 로직에서 자바보다 더 쉬운 응용이 가능하더라구요. 그래서 쉬운 C++보다는 "아주 조금" 더 생각해야할 부분이 있는 자바로 구현했어요.

 

 

on이라는 메서드는 하나의 특정 키에 여러개의 값을 매핑할 수 있게 등록하는 기능을 가집니다.

off는 등록한 값을 지우는 기능을 하죠

 

trigger는 값을 꺼내는 역할을 합니당. 지금은 그냥 리턴 타입이 없게 만들어뒀어요.

테스트용에 불과하니까요 ㅎㅎ

 

 

 

package until;

 

import java.util.ArrayList;

import java.util.HashMap;



public class DataStore implements IDataStore{

private HashMap<String, ArrayList<Object>> index = 

new HashMap<String, ArrayList<Object>>();

private static DataStore instance;

private DataStore(){}

public static DataStore sharedObject(){

if(instance == null){

instance = new DataStore();

}

return instance;

}

 

@Override

public int on(String $type, String $value) {

if(!this.index.containsKey($type)){

this.index.put($type, new ArrayList<Object>());

}

this.index.get($type).add($value);

return this.index.get($type).size();

}

 

@Override

public void off(String $type, Object $object) {

if(!this.index.containsKey($type)) return;

if(this.index.get($type).isEmpty()) return;

if(!this.index.get($type).contains($object)) return;

this.index.get($type).remove($object);

}



@Override

public void off(String $type, int $id) {

if(!this.index.containsKey($type)) return;

if(this.index.get($type).isEmpty()) return;

if($id >= this.index.get($type).size()) return;

this.index.get($type).remove($id);

}

 

@Override

public void off(String $type) {

if(!this.index.containsKey($type)) return;

if(this.index.get($type).isEmpty()) return;

this.index.get($type).clear();

}

 

@Override

public void off() {

this.index.clear();

}

 

@Override

public void trigger(String $type, Object $object) {

if(!this.index.containsKey($type)) return;

if(!this.index.get($type).contains($object)) return;

System.out.println($object);

}

 

@Override

public void trigger(String $type) {

if(!this.index.containsKey($type)) return;

for(int i=0; i<this.index.get($type).size(); ++i){

System.out.println(this.index.get($type).get(i));

}

}

}



로직을 보시면, 데이터 스토어는 맵을 갖고 있고 이 맵은 키에 매핑시킬 자료로 프리미티브값이 아닌 "배열"을 갖고 있어요. 

on에서 데이터를 등록할 때, 연관키가 없을 경우에만 이 키에 대응시키는 배열을 얼록해주는 논리를 쓰고 있죠. 이 부분에서 STL보다는 살짝 더 고민을 해줘야하는 것 같아요. 얼록이라는 과정때문이죠.

 

 

테스트 코드는 아래와 같아요.


/* 데이터 스토어를 싱글턴 유형으로 생성 */

IDataStore dataStore = DataStore.sharedObject();

 

/* 객체에 사람이라는 키로 도킨스, 매트, 해리스를 저장 */

dataStore.on("사람""도킨스");

dataStore.on("사람""매트");

dataStore.on("사람""해리스");

 

/* 객체에 동물이라는 키로 강아지, 고양이, 사자를 저장 */

dataStore.on("동물""강아지");

dataStore.on("동물""고양이");

dataStore.on("동물""사자");

 

/* 사람이라는 키로 저장되어있는 모든 데이터를 출력 */

dataStore.trigger("사람");

System.out.println("----------");

/* 동물이라는 키로 저장되어있는 모든 데이터를 출력 */

dataStore.trigger("동물");

System.out.println("----------");

/* 사람이라는 키에서 john이라는 값을 지움.(그러나 john이라는 값이 저장되어 있지 않기 때문에 아무런 일도 발생하지 않음 */

dataStore.off("사람","john");

 

/* 사람이라는 키에서 해리스라는 값을 지움.(위에서 저장했던 해리스가 지워짐) */

dataStore.off("사람""해리스");

 

/* 다시 출력. 사람이라는 키에서 해리스만 지워진것을 확인할 수 있음 */

dataStore.trigger("사람");

System.out.println("----------");

dataStore.trigger("동물");

 

System.out.println("----------");

 

 

 








댓글 없음:

댓글 쓰기