다음 편집기에서는 Java 컬렉션 클래스 소스 코드 분석에서 Set에 대한 자세한 설명을 제공합니다. 편집자님이 꽤 좋다고 생각하셔서 지금 공유하고 모두에게 참고용으로 드리도록 하겠습니다.
List와 같은 Set 컬렉션은 Collection 인터페이스에서 상속됩니다. 일반적으로 사용되는 구현 클래스에는 HashSet 및 TreeSet이 있습니다. HashSet은 HashMap을 통해 구현되고 TreeSet은 TreeMap을 통해 구현되므로 HashSet과 TreeSet 모두 자체 데이터 구조를 갖지 않는다는 점에 주목할 필요가 있습니다. 세부 사항은 다음과 같이 요약할 수 있습니다.
•Set 컬렉션의 요소는 반복될 수 없습니다. 즉, Unique
요소는 Unique
•HashSet은 요소의 해시 값으로 저장되므로 순서가 없으며 최대 1개의 null 객체를 허용합니다.
•TreeSet은 요소의 크기로 저장되므로 순서가 지정되며, null 개체를 허용하지 않습니다
•Set 컬렉션에는 get 메서드가 없으므로 요소는 반복자(Iterator)를 통해서만 탐색할 수 있으며 임의 액세스는 불가능합니다1 HashSet
static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();
소스 코드를 관찰하면 HashSet의 데이터가 HashMap의 인스턴스 객체 맵에 저장되고 맵의 키에 해당하는 반면 객체 유형 참조 PRESENT는 HashMap의 값에 해당하는 것임을 알 수 있습니다. 맵 더미 값은 실제 의미가 없습니다. HashMap의 무질서한 저장, 고유 키 값 등의 몇 가지 특성을 생각하면 반복할 수 없는 Set 컬렉션 요소의 특성과 HashSet의 무질서한 저장 특성을 자연스럽게 이해할 수 있습니다. 소스 코드 관점에서 HashSet의 기본 사용법을 이해해 보겠습니다.
• 생성자(4가지 유형)
1.HashSet() 빈 생성자, 빈 HashMap을 초기화합니다
2. HashSet(Collection 확장 E> c) 하위 집합 c를 전달하여 HashMap을 초기화합니다
3.HashSet(intinitialCapacity, float loadFactor) 빈 HashMap을 초기화하고 초기 용량 및 로드 계수를 지정합니다
public HashSet() {
map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
1.add(E e) 지정된 요소 삽입(HashMap의 put 메소드를 호출하여 구현됨)
Set<String> hashSet = new HashSet<String>();
hashSet.add("D");
hashSet.add("B");
hashSet.add("C");
hashSet.add("A");
1.contains(Object o) 집합에 지정된 요소가 포함되어 있는지 확인합니다(HashMap의 containKey 메서드를 호출하여 구현됨)
public boolean contains(Object o) { return map.containsKey(o); }
2. HashSet의 구현 클래스가 없습니다. get 메서드이므로 반복자를 통해서만 순차적으로 탐색할 수 있지만 무작위로 액세스할 수는 없습니다(HashMap에서 keySet의 반복자 구현 호출)
public Iterator<E> iterator() { return map.keySet().iterator(); }
Set<String> hashSet = new HashSet<String>();
hashSet.add("D");
hashSet.add("B");
hashSet.add("C");
hashSet.add("A");
for (Iterator iterator = hashSet.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
System.out.print(string+" ");
}//D A B C
HashMap의 키 값은 수정할 수 없기 때문에 HashSet은 요소를 수정할 수 없습니다
•요소 삭제1.remove(Object o) 지정된 요소를 삭제합니다. (구현하려면 HashMap의 제거 메소드를 호출하면 반환 값은 true입니다. 또는 false)
public boolean remove(Object o) { return map.remove(o)==PRESENT; }
public void clear() {
map.clear();
}
TreeSet은 SortedSet 구현 클래스의 유일한 인터페이스입니다. 앞서 언급한 것처럼 TreeSet은 자체 데이터 구조가 없고 TreeMap을 통해 구현되므로 TreeSet 역시 Red와 Black 이진 트리 기반의 저장 구조이므로 TreeSet은 Null 개체를 허용하지 않고 순서대로(기본 오름차순) 저장됩니다. .
private transient NavigableMap<E,Object> m; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();
위 소스 코드의 NavigableMap은 SrotedMap에서 상속된 인터페이스이고, 그 구현 클래스가 TreeMap이므로 TreeSet의 데이터는 TreeMap을 통해 저장되며, 여기의 PRESENT도 아무런 값이 없는 가상 값입니다. 실용적인 의미. 소스 코드의 관점에서 HashSet의 기본 사용법을 이해해 보겠습니다.
• 생성자(4가지 유형)
1.TreeSet() 빈 생성자, 빈 TreeMap을 초기화합니다. 기본 오름차순 order
2.TreeSet(Comparator super E> comparator)는 내림차순을 구현하는 데 자주 사용되는 사용자 정의 비교기를 전달합니다.
3.TreeSet(Collection 확장 E> c)는 하위 세트 c를 전달합니다. TreeMap 개체를 초기화하는 데 사용되며 기본 오름차순
public TreeSet() { this(new TreeMap<E,Object>()); } public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } public TreeSet(Collection<? extends E> c) { this(); addAll(c); } public TreeSet(SortedSet<E> s) { this(s.comparator()); addAll(s); }
응용 프로그램 예
//自定义一个比较器,实现降序排列 Set<Integer> treeSet = new TreeSet<Integer>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // return 0; //默认升序 return o2.compareTo(o1);//降序 } }); treeSet.add(200); treeSet.add(120); treeSet.add(150); treeSet.add(110); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); } //200 150 120 110
ArrayList<Integer> list = new ArrayList<Integer>(); list.add(300); list.add(120); list.add(100); list.add(150); System.out.println(list); //[300, 120, 100, 150] //传入一个子集,默认升序排列 TreeSet<Integer> treeSet = new TreeSet<Integer>(list); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//100 120 150 300
/*
* 传入一个有序的子集,采用子集的比较器
* 注意子集的类型必须是SortedSet及其子类或者实现类,否则将采用默认的比较器
* 所以此处subSet的类型也可以是TreeSet。
*/
SortedSet<Integer> subSet = new TreeSet<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// return 0; //默认升序
return o2.compareTo(o1);//降序
}
});
subSet.add(200);
subSet.add(120);
subSet.add(150);
subSet.add(110);
for (Iterator iterator = subSet.iterator(); iterator.hasNext();) {
Integer integer = (Integer) iterator.next();
System.out.print(integer+" ");
} //200 150 120 110
System.out.println();
Set<Integer> treeSet = new TreeSet<Integer>(subSet);
for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
Integer integer = (Integer) iterator.next();
System.out.print(integer+" ");
}//200 150 120 110
System.out.println();
treeSet.add(500);
treeSet.add(100);
treeSet.add(105);
for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
Integer integer = (Integer) iterator.next();
System.out.print(integer+" ");
}//500 200 150 120 110 105 100
1.add(E e) 지정된 요소 삽입 (TreeMap의 put 메소드 호출로 구현)
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(300);
list.add(120);
list.add(100);
list.add(150);
System.out.println(list); //[300, 120, 100, 150]
Set<Integer> treeSet = new TreeSet<Integer>();
//插入一个子集,默认升序
treeSet.addAll(list);
for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
Integer integer = (Integer) iterator.next();
System.out.print(integer+" ");
}//100 120 150 300
2.与HashSet一样,TreeSet的实现类中没有get方法,所以只能通过迭代器依次遍历,而不能随机访问(调用TreeMap中keySet的迭代器实现)。
•修改元素
TreeSet不能进行修改元素的操作,原因与HashSet一样。
•删除元素
1.remove(Object o) 删除指定元素(调用TreeMap中的remove方法实现,返回true或者false)
public boolean remove(Object o) { return m.remove(o)==PRESENT; }
2.clear() 清空元素(调用TreeMap中的clear方法实现,无返回值)
public void clear() { m.clear(); }
应用示例:
ArrayList<Integer> list = new ArrayList<Integer>(); list.add(300); list.add(120); list.add(100); list.add(150); System.out.println(list); //[300, 120, 100, 150] Set<Integer> treeSet = new TreeSet<Integer>(); //插入一个子集,默认升序 treeSet.addAll(list); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//100 120 150 300 System.out.println(treeSet.remove(100));//true for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//120 150 300 treeSet.clear(); System.out.println(treeSet.size());//0
至此,HashSet和TreeSet的存储结构及基本用法介绍完毕。
위 내용은 Java 컬렉션 클래스 소스코드의 Set 상세 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!