본문 바로가기

Java-Study

Java Study : 8주차 정리 - 컬렉션 프레임워크(제네릭, 컬렉션 프레임워크, (List, Set, Map)인터페이스)

제네릭

  • 어떤 값이 하나의 참조 자료형이 아닌 여러 참조 자료형을 사용할 수 있도록 프로그래밍 하는 것을
    제네릭 프로그래밍 이라고 한다.
  • 제네릭 프로그램은 참조 자료형이 변환될 때 이에 대한 검증을 컴파일러가 하므로 안정적이다.

 

제네릭의 필요성

  • 3D 프린터를 예시로 들면 입체 모형을 만드는데 필요한 재료가 한 가지가 아니기 때문에 재료마다 클래스를 만드는 것은 비효율적이게 된다. 이런 경우에 재료 변수의 자료형을 Object로 사용이 가능하다.
public class ThreeDPrinter {

    private Object material;    //필요한 재료를 Object로 사용
    public void setMaterial(Object material) {
        this.material = material;
    }

    public Object getMaterial() {
        return material;
    }
}
ThreeDPrinter printer = new ThreeDPrinter();

Powder p1 = new Powder();
printer.setMaterial(p1);    //자동 형 변환됨

Powder p2 = (Powder)printer.getMaterial();  //직접 형 변환을 해야 함

위처럼 Object 클래스를 사용하면 매번 형 변환을 해야 하는 번거로움이 있다. 때문에 사용하는 것이 제네릭이다.

 

제네릭 클래스 정의하기

    • 제네릭에서는 자료형을 사용하는 부분에 Object가 아닌 하나의 문자료 표현한다.
public class GenericPrinter<T> {	//제너릭 클래스 T는 type의 약자로 자료형 매개변수라 부른다.
									//나중에 클래스를 사용할 때 T 위치에 실제 사용할 자료형을 지정한다.
    private T material;

    public void setMaterial(T material) {
        this.material = material;
    }

    public T getMaterial() {
        return material;
    }
}

 

제네릭  클래스 사용하기

Powder 클래스 정의

package generics;

public class Powder{

    public void doPrinting() {
        System.out.println("Powder 재료로 출력합니다");
    }

    public String toString() {
        return "재료는 Powder 입니다";
    }
}

 

Plastic 클래스 정의

package generics;

public class Plastic{

    public void doPrinting() {
        System.out.println("Plastic 재료로 출력합니다");
    }

    public String toString() {
        return "재료는 Plastic 입니다";
    }
}

 

GenericPrinter<T> 클래스 정의

package generics;

public class GenericPrinter<T> {
    private T material; //T 자료형으로 선언한 변수

    public void setMaterial(T material) {
        this.material = material;
    }

    public T getMaterial() {    //T 자료형 변수 material을 반환하는 제네릭 메서드
        return material;
    }
}

 

GenericPrinter 클래스 사용

package generics;

public class GenericPrinterTest {
    public static void main(String[] args) {

        GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();
        //Powder 형으로 GenericPrinter 클래스 생성
        
        powderPrinter.setMaterial(new Powder());
        Powder powder = powderPrinter.getMaterial(); // 형변환 하지 않음
        System.out.println(powderPrinter);

        GenericPrinter<Plastic> plasticPrinter = new GenericPrinter<Plastic>();
        //Plastic 형으로 GenericPrinter 클래스 생성
        plasticPrinter.setMaterial(new Plastic());
        Plastic plastic = plasticPrinter.getMaterial(); // 형변환 하지 않음
        System.out.println(plasticPrinter);
    }
}

 

T 자료형에 사용할 자료형을 제한하는 <T extends 클래스>

  • 제네릭 클래스에서 T 자료형에 사용할 자료형에 제한을 둘 수 있다.
  • extends 예약어를 사용하여 제할을 둘 수 있다.
package generics;

public abstract class Material {

    public abstract void doPrinting();
}

위와 같이 Material 클래스를 추상 클래스로 정의하여 재료와 GenericPrinter<T> 클래스에서 extends로 상속 받는다.

public class Plastic extends Material

public class Powder extends Material

public class GenericPrinter<T extends Material>

 

제네릭 메서드 활용하기

package generics;

public class Point<T, V> {

    T x;
    V y;

    Point(T x, V y){
        this.x = x;
        this.y = y;
    }

    public  T getX() {  //제네릭 메서드
        return x;
    }

    public V getY() {   //제네릭 메서드
        return y;
    }
}
package generics;

public class GenericMethod {

    public static <T, V> double makeRectangle(Point<T, V> p1, Point<T, V> p2) { //제네릭 메서드
        double left = ((Number)p1.getX()).doubleValue();
        double right =((Number)p2.getX()).doubleValue();
        double top = ((Number)p1.getY()).doubleValue();
        double bottom = ((Number)p2.getY()).doubleValue();

        double width = right - left;
        double height = bottom - top;

        return width * height;
    }

    public static void main(String[] args) {

        Point<Integer, Double> p1 = new Point<Integer, Double>(0, 0.0);
        Point<Integer, Double> p2 = new Point<>(10, 10.0);

        double rect = GenericMethod.<Integer, Double>makeRectangle(p1, p2);     //<Integer, Double>는 생략 가능
        System.out.println("두 점으로 만들어진 사각형의 넓이는 " + rect + "입니다.");
    }
}

 

 

컬레션 프레임워크

  • 프로그램을 개발할 때 사용하는 자료를 어떤 구조로 관리할 것인지가 중요하다. 이 때 사용하는 것이 자료구조이며
    자바에서는 필요한 자료 구조를 미리 구현하여 패키지에서 제공하고 있는데 이름 컬레션 프레임워크라고 한다.

  • 위 그림을 보면 컬렉션 프레임워크의 전체 구조는 Collection 인터페이스와 Map 인터페이스 기반으로 이루어져 있다.
  • Collection 인터페이스는 하나의 자료를 모아서 관리하는데 필요한 기능을 제공하고
    Map 인터페이스는 쌍으로 된 자료들을 관리하는데 유용한 기능을 제공한다.

 

Collection 인터페이스

  • Collection 인터페이스 하위에 List 인터페이스와 Set 인터페이스가 있다.
  • List를 구현한 클래스는 순차적인 자료를 관리하는데 사용하는 클래스이다.
  • Set 인터페이스는 수학 시간에 배운 집합을 생각하면 되며, 집합은 순서와 상관 없이 중복을 허락하지 않기 때문에
    Set 계열의 클래스는 아이디처럼 중복되지 않는 객체를 다루는데 사용한다.

 

Map 인터페이스

  • Map 인터페이스는 하나가 아닌 쌍으로 되어있는 자료를 관리하는 메서드들이 선언되어 있다.
  • key-value 쌍이라고 표현하는데 키 값은 중복될 수 없다.

  • 왼쪽은 Map 인터페이스를 구현한 클래스 중 대표 클래스이고 오른쪽은 key-value의 예시이다.
  • Map은 기본적으로 검색용 자료구조이다 -> 어떤 key 값을 알고 잇을 때 value를 찾기 위한 자료구조
  • Map 인터페이스에 선언된 메서드 중 주요 메서드는 아래와 같다.

 

List 인터페이스

  • List 인터페이스에는 객체를 순서에 따라 저장하고 유지하는데 필요한 메서드가 선언되어 있다.
  • 대표적인 예로는 배열이 있으면 자바에서 배열을 구현한 대표 클래스로는 ArrayList, Vector가 있다.
    배열과 구현 방식은 다르지만 순차 자료 구조를 구현한 LinkedList도 있다.

ArrayList 클래스

package collection.arraylist;

import java.util.ArrayList;  // 사용할 클래스 import
import collection.Member;

public class MemberArrayList {

	private ArrayList<Member> arrayList;  // ArrayList 선언

	public MemberArrayList(){
		arrayList = new ArrayList<Member>();  //멤버로 선언한 ArrayList 생성
	}

	public void addMember(Member member){  //ArrayList에 회원을 추가하는 메서드
		arrayList.add(member);
	}

	public boolean removeMember(int memberId){  // 멤버 아이디를 매개변수로 해당 아이디를 가진 회원을
												//ArrayList에서 찾아서 제거

		for(int i =0; i<arrayList.size(); i++){ // 해당 아이디를 가진 멤버를 ArrayList에서 찾음
			Member member = arrayList.get(i);	//get() 메서드로 회원을 순차적으로 가져옴
			int tempId = member.getMemberId();
			if(tempId == memberId){            // 멤버아이디가 매개변수와 일치하면
				arrayList.remove(i);           // 해당 멤버를 삭제
				return true;                   
			}
		}

		System.out.println(memberId + "가 존재하지 않습니다");  //for 가 끝날때 까지 return 이 안된경우
		return false;
	}

	public void showAllMember(){	//전체 회원을 출력하는 메서드
		for(Member member : arrayList){
			System.out.println(member);
		}
		System.out.println();
	}
}
package collection.arraylist;

import collection.Member;

public class MemberArrayListTest {

    public static void main(String[] args) {

        MemberArrayList memberArrayList = new MemberArrayList();

        Member memberLee = new Member(1001, "이지원");     //새로운 회원 인스턴스 생성
        Member memberSon = new Member(1002, "손민국");
        Member memberPark = new Member(1003, "박서훤");
        Member memberHong = new Member(1004, "홍길동");

        memberArrayList.addMember(memberLee);       //ArrayList에 회원 추가
        memberArrayList.addMember(memberSon);
        memberArrayList.addMember(memberPark);
        memberArrayList.addMember(memberHong);

        memberArrayList.showAllMember();    //전체 회원 출력

        memberArrayList.removeMember(memberHong.getMemberId());     //memberHong 회원 삭제
        memberArrayList.showAllMember();        //회원 삭제 후 다시 전체 회원 출력
    }
}

 

ArrayList와 Vector 클래스

  • Vector 클래스도 ArrayList와 마찬가지로 배열을 구현한 클래스이다.
  • ArrayList와 Vector 클래스의 차이는 동기화 지원 여부이다.
    • 동기화는 두개 이상의 스레드가 동시에 Vector를 사용할 때 오류가 나지 않도록 실행 순설르 보장하는 것이다.
  • 스레드는 작업의 단위를 말하며, 하나의 스레드만 수행되면 단일 스레드, 두 개 이상의 스레드가 동시에 실행되는 경우를 멀티 스레드 라고 한다.
  • 두 작업이 동시에 실행되는 멀티 스레드 환경이 아닌 경우 ArrayList를 그러한 환경이면 Vector를 사용한다.

 

LinkedList 클래스

  • 배열은 생성한 때 정적인 크기로 선언하고, 자료를 중간에 삽입하거나 삭제할 때 나머지 자료를 이동시키지 않고 연속된 자료 구조를 구현하며, 크기 이상으로 요소가 추가되면 크기에 맞게 배열을 새로 생성하여 복사해야 하는 번거로움이 있다. 이러한 단점을 개선한 자료 구조가 링크드 리스트이다.
  • 링크드 리스트의 각 요소는 다음 요소를 가르키는 주소 값을 가지기 때문에 요소를 추가하거나 삭제하는 경우 
    나머지 요소를 옮기고 요소가 가리키는 주소 값만 변경해 주면 된다.
  • 사용하는 자료의 변동이 많은 경우에는 링크드 리스트를, 거의 없는 경우에는 배열을 사용하는 것이 효율적이다.
package collection.linkedlist;

import java.util.LinkedList;

public class LinkedListTest {

    public static void main(String[] args) {

        LinkedList<String> myList = new LinkedList<String>();

        myList.add("A");    //링크드 리스트에 요소 추가
        myList.add("B");
        myList.add("C");

        System.out.println(myList);     //리스트 전체 출력
        
        myList.add(1, "D"); //링크드 리스트의 첫 번째 위치에 D 추가
        System.out.println(myList);

        myList.addFirst("O");   //링크드 리스트의 맨 앞에 0 추가
        System.out.println(myList);
        System.out.println(myList.removeLast());    //링크드 리스트 맨 뒤 요소 삭제후 해당 요소 출력

        System.out.println(myList);

    }
}

 

ArrayList로 스택과 큐 구현하기

  • 스택은 상자를 쌓듯이 자료를 관리하는 방식으로 맨 나중에 추가된 데이터를 먼저 꺼내는(Last In First Out:LIFO) 방식
    • 스택에 자료를 추가하는 것을 push(), 자료를 꺼내는 것을 pop() 이라고 한다.
  • 큐는 대기열처럼 먼저 추가된 데이터부터 꺼내서 사용하는(First In First Out:FIFO) 방식

스택 구현하기

package collection.arraylist;

import java.util.ArrayList;

class MyStack{

    private ArrayList<String> arrayStack = new ArrayList<String>();

    public void push(String data) {     //스택의 맨 뒤에 요소를 추가
        arrayStack.add(data);
    }

    public String pop() {   //스택의 맨 뒤에서 요소를 꺼냄
        int len = arrayStack.size();    //ArrayList에 저장된 유효한 자료의 개수
        if(len == 0 ) {
            System.out.println("스택이 비었습니다.");
            return null;
        }

        return(arrayStack.remove(len-1));   //맨 뒤에 있는 자료를 반환하고 배열에서 제거
    }
}

public class StackTest {

    public static void main(String[] args) {

        MyStack stack = new MyStack();
        stack.push("A");
        stack.push("B");
        stack.push("C");

        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
    }
}

 

큐 구현하기

package collection.arraylist;

import java.util.ArrayList;

class MyQueue{

    private ArrayList<String> arrayQueue = new ArrayList<String>();

    public void enQueue(String data) {  //큐의 맨 뒤에 추가
        arrayQueue.add(data);
    }

    public String deQueue() {   //큐의 맨 앞에서 꺼냄
        int len = arrayQueue.size();
        if(len == 0 ) {
            System.out.println("큐가 비었습니다.");
            return null;
        }

        return(arrayQueue.remove(0));   //맨 앞의 자료 반환하고 배열에서 제거
    }
}

public class QueueTest {

    public static void main(String[] args) {

        MyQueue queue = new MyQueue();
        queue.enQueue("A");
        queue.enQueue("B");
        queue.enQueue("C");

        System.out.println(queue.deQueue());
        System.out.println(queue.deQueue());
        System.out.println(queue.deQueue());
    }
}

 

Collection 요소를 순회하는 Iterator

  • 순서가 없는 인터페이스를 구현한 경우에 Iterator를 사용하여 요소를 순환시킨다.
public boolean removeMember(int memberId){  // 멤버 아이디를 매개변수로 해당 아이디를 가진 회원을
												//ArrayList에서 찾아서 제거
		Iterator<Member> ir = arrayList.iterator();	//Iterator 반환
		while(ir.hasNext()) {		//요소가 있는 동안
			Member member = ir.next();	//다음 회원을 반환받음
			int tempId = member.getMemberId();
			if(tempId == memberId){            // 멤버아이디가 매개변수와 일치하면
				arrayList.remove(member);           // 해당 멤버를 삭제
				return true;                   // true 반환
			}
		}

		System.out.println(memberId + "가 존재하지 않습니다");  //for 가 끝날때 까지 return 이 안된경우
		return false;
	}

 

 

Set 인터페이스

  • 순서와 상관없이 중복을 허용하지 않는 경우에는 Set 인터페이스를 구현한 클래스를 사용한다.
  • Set 인터페이스룰 구현한 대표 클래스에는 HashSet 과 TreeSet이 있다.

HashSet 클래스

  • HashSet 클래스는 집합 자료 구조를 구현하며 중복을 허용하지 않는다.
package collection.hashset;

import java.util.HashSet;

public class HashSetTest {

    public static void main(String[] args) {

        HashSet<String> hashSet = new HashSet<String>();
        hashSet.add(new String("임정순"));
        hashSet.add(new String("박현정"));
        hashSet.add(new String("홍연의"));
        hashSet.add(new String("강감찬"));
        hashSet.add(new String("강감찬"));

        System.out.println(hashSet);
    }
}

중복을 허용하지 않음

 

HashSet 활용

package collection.hashset;

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

import collection.Member;

public class MemberHashSet {
    private HashSet<Member> hashSet;    //HashSet 선언

    public MemberHashSet(){
        hashSet = new HashSet<Member>();    //HashSet 생성
    }

    public void addMember(Member member){   //HashSet에 회원 추가
        hashSet.add(member);
    }

    public boolean removeMember(int memberId){  //매개변수로 받은 회원 아이디에 해당하는 회원 삭제

        Iterator<Member> ir = hashSet.iterator();   //Iterator를 활용해 순회

        while( ir.hasNext()){
            Member member = ir.next();
            int tempId = member.getMemberId();
            if( tempId == memberId){
                hashSet.remove(member);
                return true;
            }
        }

        System.out.println(memberId + "가 존재하지 않습니다.");
        return false;
    }

    public void showAllMember(){    //모든 회원 출력
        for(Member member : hashSet){
            System.out.println(member);
        }
        System.out.println();
    }
}
package collection.hashset;

import collection.Member;

public class MemberHashSetTest {

    public static void main(String[] args) {

        MemberHashSet memberHashSet = new MemberHashSet();

        Member memberLee = new Member(1001, "이지원");
        Member memberSon = new Member(1002, "손민국");
        Member memberPark = new Member(1003, "박서훤");


        memberHashSet.addMember(memberLee);
        memberHashSet.addMember(memberSon);
        memberHashSet.addMember(memberPark);
        memberHashSet.showAllMember();

        Member memberHong = new Member(1003, "홍길동");  //1003 아이디 중복
        memberHashSet.addMember(memberHong);
        memberHashSet.showAllMember();
    }
}

 

TreeSet 클래스

  • Tree로 시작하는 클래스는 데이터를 추가한 후 결과를 출력하면 결과 값이 정렬된다.
  • TreeSet은 자료의 중복을 허용하지 않을면서 출력 결과 값을 정렬하는 클래스이다.
package collection.treeset;

import java.util.TreeSet;

public class TreeSetTest {

    public static void main(String[] args) {

        TreeSet<String> treeSet = new TreeSet<String>();
        treeSet.add("홍길동");
        treeSet.add("강감찬");
        treeSet.add("이순신");

        for(String str : treeSet) {
            System.out.println(str);
        }
    }
}

 

TreeSet 활용

package collection.treeset;

import java.util.Iterator;
import java.util.TreeSet;

import collection.Member;

public class MemberTreeSet {

    private TreeSet<Member> treeSet;

    public MemberTreeSet(){
        treeSet = new TreeSet<Member>();
    }

    public void addMember(Member member){   //TreeSet에 회원을 추가하는 메서드
        treeSet.add(member);
    }

    public boolean removeMember(int memberId){  //TreeSet에서 회원을 삭제하는 메서드

        Iterator<Member> ir = treeSet.iterator();

        while( ir.hasNext()){
            Member member = ir.next();
            int tempId = member.getMemberId();
            if( tempId == memberId){
                treeSet.remove(member);
                return true;
            }
        }

        System.out.println(memberId + "가 존재하지 않습니다.");
        return false;
    }

    public void showAllMember(){    //전체 회원을 출력하는 메서드
        for(Member member : treeSet){
            System.out.println(member);
        }
        System.out.println();
    }
}
package collection.treeset;

import collection.Member;

public class MemberTreeSetTest {

    public static void main(String[] args) {

        MemberTreeSet memberTreeSet = new MemberTreeSet();


        Member memberPark = new Member(1003, "박서훤");
        Member memberLee = new Member(1001, "이지원");
        Member memberSon = new Member(1002, "손민국");


        memberTreeSet.addMember(memberLee);
        memberTreeSet.addMember(memberSon);
        memberTreeSet.addMember(memberPark);
        memberTreeSet.showAllMember();

        Member memberHong = new Member(1003, "홍길동");  //1003 아이디 중복
        memberTreeSet.addMember(memberHong);
        memberTreeSet.showAllMember();
    }
}

위 코드를 실행해 보면 오류가 발생하게 되는데 그 이유는 TreeSet의 요소로 Member 클래스를 추가할 때 어떤 기준으로
노드를 비교하여 트리를 형성해야 하는지 구현하지 않았기 때문이다.

 

Comparable 인터페이스와 Comparator 인터페이스

  • Comparable과 Comparator는 정렬을 구현할 수 있게 해주는 인터페이스이다.
  • 정렬 방식은 정렬 기준 값이 있는 클래스에 구현하면 된다.

Comparable 인터페이스 구현

Member.java에 정렬 기준 구현
@Override
    public int compareTo(Member member) {	//compareTo 메서드 재정의

        return (this.memberId - member.memberId);   //오름차순
    }

Comparator 인터페이스 구현

@Override
    public int compare(Member2 mem1, Member2 mem2) {	//전달받은 두 매개변수를 비교함

        return mem1.getMemberId() - mem2.getMemberId();
    }
package collection.treeset;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

class MyCompare implements Comparator<String>{

    @Override	//내림차순으로 정렬
    public int compare(String s1, String s2) {
        return (s1.compareTo(s2)) *-1 ;
    }
}

public class ComparatorTest {

    public static void main(String[] args) {

        Set<String> set = new TreeSet<String>();	//TreeSet 생성자의 매개변수로 정렬 방식을 지정
        set.add("aaa");
        set.add("ccc");
        set.add("bbb");

        System.out.println(set);
    }
}

 

 

Map 인터페이스

  • Map 인터페이스는 자료를 쌍으로 관리하는데 필요한 메서드가 정의되어 있다.
  • Map 인터페이스를 구현한 클래스는 내부적으로 해시 알고리즘에 의해 구현되어 있다.
  • 가장 많이 사용하는 클래스는 HashMap 클래스이다.

HashMap 클래스

package map.hashmap;

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

import collection.Member;

public class MemberHashMap {

    private HashMap<Integer, Member> hashMap;

    public MemberHashMap()
    {
        hashMap = new HashMap<Integer, Member>();
    }

    public void addMember(Member member){   //HashMap에 회원을 추가하는 메서드

        hashMap.put(member.getMemberId(), member);  //key-value 쌍으로 추가

    }

    public boolean removeMember(int memberId){  //HashMap에서 회원을 삭제하는 메서드

        if(hashMap.containsKey(memberId)){  //HashMap에 회원을 추가하는 메서드
            hashMap.remove(memberId);   //해당 회원 삭제
            return true;
        }

        System.out.println(memberId + "가 존재하지 않습니다.");
        return false;
    }

    public void showAllMember(){    //Iterator를 사용해 전체 회원을 출력하는 메서드
        Iterator<Integer> ir = hashMap.keySet().iterator();
        while (ir.hasNext()){   //다음 key가 있으면
            int key = ir.next();    //key 값을 가져와서
            Member member = hashMap.get(key);   //key로부터 value 가져오기
            System.out.println(member);
        }
        System.out.println();
    }
}

 

TreeMap 클래스

  • Map 인터페이스를 구현한 클래스 중 key 값으로 자료를 정렬하려면 TreeMap을 사용할 수 있다.
  • key 값으로 정렬하므로 key 값에 해당하는 클래스에 Comparable이나 Comparator 인터페이스를 구현해야 한다.
package map.treemap;

import java.util.Iterator;
import java.util.TreeMap;

import collection.Member;

public class MemberTreeMap {

    private TreeMap<Integer, Member> treeMap;

    public MemberTreeMap()
    {
        treeMap = new TreeMap<Integer, Member>();
    }

    public void addMember(Member member){

        treeMap.put(member.getMemberId(), member);  //key-value 쌍으로 추가
    }

    public boolean removeMember(int memberId){

        if(treeMap.containsKey(memberId)){
            treeMap.remove(memberId);   //key 값에 맞는 자료 삭제
            return true;
        }

        System.out.println(memberId + "가 존재하지 않습니다.");
        return false;
    }

    public void showAllMember(){
        Iterator<Integer> ir = treeMap.keySet().iterator();
        while (ir.hasNext()){
            int key = ir.next();
            Member member = treeMap.get(key);
            System.out.println(member);
        }
        System.out.println();
    }
}
package map.treemap;

import collection.Member;

public class MemberTreeMapTest {

    public static void main(String[] args) {

        MemberTreeMap memberHashMap = new MemberTreeMap();

        Member memberPark = new Member(1003, "박서훤");    //회원 아이디 순서와 상관없이 회원 추가
        Member memberLee = new Member(1001, "이지원");
        Member memberHong = new Member(1004, "홍길동");
        Member memberSon = new Member(1002, "손민국");

        memberHashMap.addMember(memberPark);    
        memberHashMap.addMember(memberLee);
        memberHashMap.addMember(memberHong);
        memberHashMap.addMember(memberSon);

        memberHashMap.showAllMember();

        memberHashMap.removeMember(1004);
        memberHashMap.showAllMember();
    }
}