Java学习笔记----------集合Set

Java集合-----Set
集合:就像一种容器,可以把多个对象放进该容器中。
Java集合分为:Set、List、Map三种体系。
  Set:无序的,不可重复的;
  List:有序的,可重复的;
  Map:代表有映射关系的集合,Map保存的每一项数据都是key-value对。
注意:Java 5后添加了Queue体系,代表一种队列集合实现。

集合和数组对比:
1.数组一旦初始化,长度不可变;
2.数组无法保存具有映射关系的数据,例如成绩表:语文---79;
3.数组的元素可以是基本类型的值,也可以是对象,而集合只能是保存对象;

Java集合由两个接口派生而出:Collection和Map,这两个是Java集合框架的根接口。
他们包含的子接口和实现类如下图:

1.Collection 接口是List、Set、Queue接口的父接口,定义了如下操作集合元素的方法:
  1.1 boolean add(Object o) 
          向集合里添加一个元素,如果集合对象被添加操作改变则返回true;
  1.2 boolean addAll(Collection c) 
          将指定 collection 中的所有元素都添加到此 collection 中,如果集合对象被添加返回true; 
  1.3 void clear() 
          移除此 collection 中的所有元素,将集合长度变为0; 
  1.4 boolean contains(Object o) 
          如果此 collection 包含指定的元素,则返回 true。 
  1.5 boolean containsAll(Collection c) 
          如果此 collection 包含指定 collection 中的所有元素,则返回 true。 
  1.6 boolean equals(Object o) 
          比较此 collection 与指定对象是否相等。 
  1.7 int hashCode() 
          返回此 collection 的哈希码值。 
  1.8 boolean isEmpty() 
          如果此 collection 不包含元素,则返回 true。 
  1.9 Iterator iterator() 
          返回一个Iterator对象,用于遍历集合里的元素; 
  1.10 boolean remove(Object o) 
          从此 collection 中移除指定元素的单个实例,如果存在的话返回true; 
  1.11 boolean removeAll(Collection c) 
          移除此 collection 中那些也包含在指定 collection 中的所有元素,如果存在的话返回true;  
  1.12 boolean retainAll(Collection c) 
          仅保留此 collection 中那些也包含在指定 collection 的元素,如果存在的话返回true;  
  1.13 int size() 
          返回此 collection 中的元素个数;
  1.14 Object[] toArray() 
          该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素; 
eg:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public class CollectionTest {
	public static void main(String[] args) {
		Collection c = new ArrayList();
		// 添加元素
		c.add("孙悟空");
		c.add(6);
		// 输出集合元素个数
		System.out.println("c的集合个数为:" + c.size());
		// 移除指定元素
		c.remove(6);
		System.out.println("c的集合个数为:" + c.size());
		// 判断集合是否包含某个元素
		System.out.println("判断集合是否包含某个元素:" + c.contains("孙悟空"));
		c.add("Java EE");
		System.out.println("c的集合元素:" + c);
		Collection books = new HashSet();
		books.add("孙悟空");
		books.add("Java讲义");
		// c集合是否完全包含books集合
		System.out.println("c集合是否完全包含books集合" + c.containsAll(books));
		// 用c集合减去books集合里的元素
		c.removeAll(books);
		System.out.println("c的集合元素:" + c);
		// 删除c集合里的所有元素
		c.clear();
		System.out.println("c的集合元素:" + c);
		// books 集合里面只剩下c集合里也包含的元素
		books.removeAll(c);
		System.out.println("books的集合元素:" + books);
	}
}
运行结果:
		 c的集合个数为:2
		 c的集合个数为:1
		 判断集合是否包含某个元素:true
		 c的集合元素:[孙悟空, Java EE]
		 c集合是否完全包含books集合false
		 c的集合元素:[Java EE]
		 c的集合元素:[]
		 books的集合元素:[Java讲义, 孙悟空]

2.使用Iterator接口遍历集合元素
    Iterator 主要用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。
	Iterator 仅用于遍历集合,必须依附于Collection对象。
	使用 Iterator 对集合元素进行迭代时,并不是把集合元素本身传给迭代变量,而是把集合元素的值
	传给了迭代变量,所以修改迭代变量的值对集合元素本身没有任何影响。
提供的方法:
    1.boolean hasNext()如果仍有元素可以迭代,则返回 true。 
	2.Object next()返回迭代的下一个元素。 
	3.void remove()删除集合里上一次next方法返回的元素。
eg:
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class IteratorTest {
	public static void main(String[] args) {
		Collection books = new HashSet();
		books.add("A书");
		books.add("B书");
		books.add("C书");
		// 获取books集合对应的迭代器
		Iterator it = books.iterator();
		while (it.hasNext()) {
			// it.next()返回的是一个对象类型,需要强制转换
			String book = (String) it.next();
			System.out.println(book);
			if (book.equals("B书")) {
				// 从集合中删除上一次next方法返回的元素
				it.remove();
			}
			// book变量赋值,不会改变集合元素本身
			book = "C书";
		}
		System.out.println(books);
	}
}

3.使用foreach循环遍历集合元素
  比起Iterator更加简洁,同样集合不能被改变。
eg:
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class ForeachTest {
	public static void main(String[] args) {
		Collection books = new HashSet();
		books.add("A书");
		books.add("B书");
		books.add("C书");
		for(Object obj:books){
			String book=(String)obj;
			System.out.println(book);
			if(book.equals("B书")){
				books.remove(book);
			}
		}
		System.out.println(books);
	}
}

4.Set 集合
无序的,不可重复,与Collection基本一样,无提供而外的方法。
  4.1 HashSet 类:按hash算法存储集合中的元素,具有很好的存取和存取性能,具有以下特点:
      1).不能保证元素的排列顺序,顺序可能和添加顺序不同,也可能发生改变。
	  2).HashSet不是同步的,多个线程同时对HashSet操作,必须通过代码保证其同步。
	  3).集合元素可以是null;
HashSet 集合判断两个元素是否相等是同时通过equals()方法和两个对象的hashCode()方法返回值是否相等,
又因为set集合的规则是不能存在相同的元素,所以在重写该对象对应类的equals()方法,则也应该重写hashCode()方法。
eg:
import java.util.HashSet;

// 类A的equals()方法的返回true,但没有重写其hashCode()方法
class A {
	public boolean equals(Object obj) {
		return true;
	}
}

// 类B的hanshCode()方法总是返回1,但是没有重写equals()方法
class B {
	public int hashCode() {
		return 1;
	}
}

// 类C的hashCode()方法返回2,且重写了equals()方法
class C {
	public int hashCode() {
		return 2;
	}

	public boolean equals(Object obj) {
		return true;
	}
}

public class HashSetTest {
	public static void main(String[] args) {
		HashSet books = new HashSet();
		// 分别想books集合中添加两个A对象,两个B对象,两个C对象
		books.add(new A());
		books.add(new A());
		books.add(new B());
		books.add(new B());
		books.add(new C());
		books.add(new C());
		System.out.println(books);
	}
}
hashCode()方法重写的基本规则
  1).程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值;
  2).当两个对象通过equals()方法比较返回true时,两个对象的hashCode()方法应返回相等值;
  3).对象中用作equals()方法比较的标准field,都应该用计算hashCode值。
4.2 LinkedHashSet 类
	LinkedHashSet集合也是更加hashCode值来决定元素的存储位置,但他可以保存元素插入的顺序,
也因为要维护元素的插入顺序,因此性能略低于HashSet的性能,但是迭代访问所有元素时有很好的性能。
LinkedHashSet 同样不能出现相同的元素,因为它依然是HashSet.
eg:
import java.util.LinkedHashSet;

public class LinkedHashSetTest {
	public static void main(String[] args) {
		LinkedHashSet books = new LinkedHashSet();
		books.add("A书");
		books.add("B书");
		System.out.println(books);
		books.remove("A书");
		books.add("C书");
		System.out.println(books);
	}
}
运行结果:
[A书, B书]
[B书, C书]
  
4.3 TreeSet 类
	TreeSet可以确保集合元素处于排序状态(元素有序),它除了提供HashSet有的方法外还提供了以下方法:
	1).Comparator comparator():如果采用的是定制排序,返回所使用的Comparator;
	              如果采用自然排序,返回null。
	2).Object first() 返回集合中的第一个元素
	3).Object last() 返回集合中的最后一个元素
	4).Object lower(Object e)返回集合中位于指定元素之前的元素(既小于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素)
	5).Object higher(Object e)返回集合中位于指定元素之后的元素(既大于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素)
	6).SortedSet subSet(E fromElement, E toElement) )返回此Set的子集合,范围从fromElement(包含)到toElement(不包含)
	7).SortedSet headSet(Object toElement)返回小于toElement小的set子集
	8).SortedSet tailSet(Object fromElement)返回大于或者等于fromElement的Set子集
eg:
import java.util.TreeSet;

public class TreeSetTest {
	public static void main(String[] args) {
		TreeSet nums = new TreeSet();
		nums.add(5);
		nums.add(2);
		nums.add(-1);
		nums.add(3);
		nums.add(6);
		System.out.println(nums);
		// 输出集合中第一个元素
		System.out.println(nums.first());
		// 输入元素中最后一个
		System.out.println(nums.last());
		// 返回小于4的,不包含4的元素集合
		System.out.println(nums.headSet(4));
		// 返回大于等于3的元素集合
		System.out.println(nums.tailSet(3));
		// 返回大于等于1小于4的子集合
		System.out.println(nums.subSet(1, 4));
	}
}
运行结果:
		[-1, 2, 3, 5, 6]
		-1
		6
		[-1, 2, 3]
		[3, 5, 6]

4.4 EnumSet 类
    EnumSet是一个枚举类设计的集合类,EnumSet中的每个元素都必须是指定枚举类型的枚举值。
EnumSet的集合元素也是有序的,以枚举值在枚举类的定义顺序来决定集合元素的顺序。
	EnumSet不允许加入null元素,否则会报错。EnumSet内部以单位向量存储,占用内存小,运行高效,尤其批量操作。
	EnumSet提供了如下常用static方法创建对象:
	1).allOf(Class elementType) 
	      创建一个指定枚举类里所有包含枚举值的EnumSet集合 
	2).complementOf(EnumSet s) 
          创建一个其元素类型与指定枚举 set 相同的枚举 set,最初包含指定 set 中所不包含的此类型的所有元素。 
	3).copyOf(Collection c) 
          使用一个普通集合来创建EnumSet集合 
	4).copyOf(EnumSet s) 
          创建一个与指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合
	5).noneOf(Class elementType) 
          创建一个具有指定元素类型的空枚举 set。 
	6).of(E e1, E e2, E e3, E e4, E e5......) 
          创建一个最初包含指定元素的枚举 set。 
	7).range(E from, E to) 
          创建一个包含从frome枚举值到to枚举值方位内的所有枚举值的EunmSet集合 
eg:
import java.util.EnumSet;

enum Season {
	A, B, C, D;
}

public class EnumSetTest {
	public static void main(String[] args) {
		// 创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值
		EnumSet es1 = EnumSet.allOf(Season.class);
		System.out.println(es1);
		// 创建一个控计划,只想Season枚举类
		EnumSet es2 = EnumSet.noneOf(Season.class);
		System.out.println(es2);
		// 添加两个元素
		es2.add(Season.D);
		es2.add(Season.A);
		System.out.println(es2);
		// 以指定枚举值创建EnumSet集合
		EnumSet es3 = EnumSet.of(Season.A, Season.B);
		System.out.println(es3);
		// 创建从B到D的EnumSet
		EnumSet es4 = EnumSet.range(Season.B, Season.D);
		System.out.println(es4);
		// 创建与es4没有的Season原色的EnumSet
		EnumSet es5 = EnumSet.complementOf(es4);
		System.out.println(es5);
	}
}
运行结果:
		[A, B, C, D]
		[]
		[A, D]
		[A, B]
		[B, C, D]
		[A]

5 各Set实现类性能分析
	HashSet 和 TreeSet ,HashSet的整体性能总比TreeSet好,特别是添加和查询操作,只有当一个保持排序的Set时
才使用TreeSet。
	LinkedHashSet 和 HashSet ,HashSet的插入和删除略快,但是LinkedHashSet的遍历会比HashSet更快。
	EnumSet 是所有set中性能最好的,但它只鞥呢保存同一个枚举类的值作为集合。
	set的三个实现类HashSet、TreeSet、EnumSet都是线程不安全的。多个线程访问或操作Set,必须手动保证该Set的同步性.

你可能感兴趣的:(Java)