/*
 * 集合概述	
 * 存储对象的方式:1、数组  2、集合
 * 数组存储对象的缺点:1、一旦创建,长度固定 ;2、真实存在数组的对象不可知;
 * 集合分为:Collection 和 Map
 * 
 * Collection接口
 * 			| --- List接口:元素有序,可以重复(动态数组 [a,b,c,c])
 * 					| --- ArrayList 实现类
 * 					| --- LinkedList 实现类 (链表,频繁插入删除)
 * 					| --- Vector 
 * 			| --- Set接口:元素无序,不可重复 (数学集合 {a,b,c,d})
 * 					| --- HashSet 实现类
 * 					| --- LinkedHashSet 实现类
 * 					| --- TreeSet 实现类
 
 * Map接口:
 * 具有映射关系的key-value对的集合(数学函数 y=f(x))
 * 	
 */

 /*
 * java.util.Interface Collection<E>
 * 实现类ArrayList为例说明
 * 1、int size() : 返回集合中元素的个数
 * 2、boolean add(E e)  : 向集合添加一个元素
 * 3、boolean addAll(Collection<? extends E> c)  :向集合添加另一个集合
 * 4、boolean isEmpty()  :判断集合是否为空
 * 5、void clear()  :清空集合中所有元素
 */
		Collection coll = new ArrayList();

		coll.add("A");
		coll.add("B");
		coll.add(123);
		System.out.println(coll.size());
		System.out.println(coll.isEmpty());
		coll.clear();
		System.out.println(coll.isEmpty());

/*
 * 6、boolean contains(Object o)  :是否包含某个元素
 * 判断依据:根据元素所在类的equals()方法进行判断:如果存入自定义类对象,需要重写equals()方法
 * 7、boolean containsAll(Collection<?> c)  :是否包含某个集合
 * 8、boolean retainAll(Collection<?> c)  :两个集合的交集,返回给当前集合
 * 9、boolean remove(Object o)  :删除某个元素
 * 10、boolean removeAll(Collection<?> c)  :两个集合的差集
 * 11、boolean equals(Object o)  :两个集合中的元素是否完全相同
 * 12、Object[] toArray()  :将集合转换为数组
 * 13、Iterator<E> iterator()  :返回Iterator接口实现类的对象,进而实现集合的遍历;
 */
	@Test
	public void test04() {
		Collection coll = new ArrayList();

		coll.add("AA");
		coll.add("B");
		coll.add(123);
		a a1 = new a();
		coll.add(a1);
		System.out.println(coll.contains(new String("AA")));
		System.out.println(coll.contains(a1)); //true
		System.out.println(coll.contains(new a())); //true

		Collection coll1 = new ArrayList();
		coll1.add("AA");
		coll1.add("B");
		System.out.println(coll.containsAll(coll1)); //true
		System.out.println(coll.retainAll(coll1)); // true
		System.out.println(coll); // [AA, B]

		System.out.println(coll.remove("AA")); //true
		System.out.println(coll); //[B]

		Collection coll3 = new ArrayList();
		coll3.add("AA");
		coll3.add("B");
		coll3.add(123);
		a a2 = new a();
		System.out.println(coll3.removeAll(coll1));  //true
		System.out.println(coll3); // [123]

		System.out.println(coll1.equals(coll1)); //true

		Collection coll4 = new ArrayList();
		coll4.add("AA");
		coll4.add("B");
		coll4.add(123);
		a a3 = new a();
		coll4.add(a3);
		Object[] object = coll4.toArray();
		for (int i = 0; i < object.length; i++) {
			System.out.println(object[i]);
		}

		Iterator i = coll4.iterator();
		while (i.hasNext()) {
			Object object2 = (Object) i.next();
			System.out.println(object2);
		}

	}
	
/*
 * List相对于Collection,新增的方法
 * 1、void add(int index, E element)  :在指定索引位置添加元素
 * 2、E get(int index)  :获取指定索引位置的元素
 * 3、E remove(int index)  :删除指定索引的元素
 * 4、E set(int index, E element)  :修改指定索引的元素
 * 5、int indexOf(Object o)  :返回obj在集合中首次出现的位置,否则返回-1
 * 6、int lastIndexOf(Object o)  :返回obj在集合中最后一次出现的位置,否则返回-1
 * 7、List<E> subList(int fromIndex, int toIndex)  :返回fromIndex到toIndex的一个子List
 */
	@Test
	public void test05() {
		List list1 = new ArrayList();
		list1.add(123);
		list1.add(456);
		list1.add("ABC");
		list1.add("def");
		list1.add(new a());
		System.out.println(list1); //[123, 456, ABC, def, package01.A@1386918]
		list1.add(0, 111);
		System.out.println(list1); //[111, 123, 456, ABC, def, package01.A@1386918]
		System.out.println(list1.get(0)); // 111
		System.out.println(list1.remove(1)); // 123
		list1.set(1, 222);
		System.out.println(list1); // [111, 222, ABC, def, package01.A@1386918]

		System.out.println(list1.indexOf(new a())); // 4
		System.out.println(list1.lastIndexOf(222)); // 1

		System.out.println(list1.subList(2, 4)); // [ABC, def]
	}
	
/*
 * Set
 * 无序性:存储元素的位置是随机的; 
 * 不可重复:不能添加相同元素
 * 如何判断元素是否重复:通过equals()和 hashCode()方法
 * 
 * Set首先使用hashCode()计算对象的hash值,决定对象在Set的存储位置;
 * 如果没有hash值,则存储到此位置,如果有此hash值,则比较equals()是否相同;
 * 如果equals()相同,则无法添加,否则返回false;
 * 要求:hashCode()与equals()结果一致;
 */

	@Test
	public void test06() {
		Set set1 = new HashSet();
		set1.add(123);
		set1.add(456);
		set1.add("ABC");
		set1.add("BBB");
		set1.add(new String("ABC"));
		set1.add(null);
		set1.add(new a("hmm"));
		a a1 = new a("hmm");
		set1.add(a1);
		System.out.println(a1.hashCode()); //103463
		System.out.println(set1); // [null, ABC, BBB, A [name=hmm], 456, 123]
	}

/*
 * LinkedHashSet : 使用链表维护了一个元素顺序,可以按照添加顺序遍历
 */
	@Test
	public void test07() {
		Set set1 = new LinkedHashSet();
		set1.add(123);
		set1.add(456);
		set1.add("ABC");
		set1.add("BBB");
		set1.add(new String("ABC"));
		set1.add(null);
		set1.add(new a("hmm"));
		a a1 = new a("hmm");
		set1.add(a1);
		System.out.println(set1); // [123, 456, ABC, BBB, null, A [name=hmm]]
		Iterator i = set1.iterator();
		while (i.hasNext()) {
			System.out.println(i.next());
		}
	}


/*
 * TreeSet
 * 1、TreeSet中添加的元素必须是相同类型
 * 2、按照集合中元素指定的顺序遍历,String的
 */
	@Test
	public void test08() {
		Set set1 = new TreeSet();
		set1.add("ABC");
		set1.add("BBB");
		set1.add(new String("1BC"));
		set1.add(new String("aBC"));
		set1.add(new String("ABC"));
		System.out.println(set1); // [1BC, ABC, BBB, aBC]
	}

/*
 * TreeSet 自然排序
 * 1、自定义类的自然排序,需要自定义类实现Comparable接口,并重写compareTo()方法
 * 自然排序:首先按照compareTo()比较,根据属性值比较;compareTo()/hashCode()/equals() 方法结果一致
 */
	@Test
	public void test09(){
		Set set1 = new TreeSet();
		set1.add(new a("zhangs",23));
		set1.add(new a("lisi",20));
		set1.add(new a("wangw",33));
		set1.add(new a("zhaoliu",11));
		set1.add(new a("sunq",6));
		set1.add(new a("wangw",11));
		set1.add(new a("wangw",9));
		System.out.println(set1);
		Iterator i = set1.iterator();
//		[A [name=lisi, age=20], A [name=sunq, age=6], A [name=wangw, age=9], A [name=wangw, age=11], A [name=wangw, age=33], A [name=zhangs, age=23], A [name=zhaoliu, age=11]]
		while (i.hasNext()) {
			System.out.println(i.next());
		}
	}

/*
 * TreeSet 定制排序
 * 1、自定义类的定制排序, 创建一个实现Comparator接口的子类,并重写compare()方法,在compare()方法中实现排序规则
 * 2、将Comparator接口的子类传递给TreeSet构造器
 * 3、TreeSet中添加compare()中的对象
 */
	@Test
	public void test10() {
		Comparator c = new Comparator(){
			@Override
			public int compare(Object o1, Object o2) {
				if (o1 instanceof B && o2 instanceof B) {
					B b1 = (B)o1;
					B b2 = (B)o2;
					return b1.getName().compareTo(b2.getName()) == 0 ? b1.getAge().compareTo(b2.getAge()) : b1.getName().compareTo(b2.getName());
//					return b1.getName().compareTo(b2.getName()) ;
				}
				return 0;
			}
		};

		TreeSet set1 = new TreeSet(c);
		set1.add(new B("zhangs",23));
		set1.add(new B("lisi",20));
		set1.add(new B("wangw",33));
		set1.add(new B("zhaoliu",11));
		set1.add(new B("sunq",6));
		set1.add(new B("wangw",11));
		set1.add(new B("wangw",9));

		Iterator i = set1.iterator();
		System.out.println(set1);
//		[b [name=lisi, age=20], b [name=sunq, age=6], b [name=wangw, age=9], b [name=wangw, age=11], b [name=wangw, age=33], b [name=zhangs, age=23], b [name=zhaoliu, age=11]]
		while (i.hasNext()) {
			System.out.println(i.next());
		}
	}
	
/*
 * Map接口 
 * 	| --- HashMap:Map主要实现类 
 * 	| --- LinkedHashMap 
 * 	| --- TreeMap: 
 * 	| ---Hashtable 
 * 		| --- properties 
 * HashMap常用方法
 * key是Set实现,不可以重复,value由Collection实现,可以重复;key-value由Set实现,不可以重复;
 * 向HashMap添加key-value时,会调用key的equals()方法,判断key是否相同,若相同,则会覆盖添加;
 * 
 * 1、V put(K key, V value):向Map中添加一个key-value 2、int size() :Map的key-value个数
 * 3、V remove(Object key) :按照key删除key-value 4、V get(Object key)
 * :获取指定key的key-value 5、Set<K> keySet() : 获取key的set,用于遍历 6、Collection<V>
 * values() :获取value的Collection,用于遍历 7、Set<Map.Entry<K,V>> entrySet()
 * :获取key-value的Set
 */
@Test
public void test11() {
	Map m = new HashMap();
	m.put("a", 111);
	m.put("b", 22);
	m.put("c", 3);
	m.put("a", 123);
	System.out.println(m); // {b=22, c=3, a=123}
	System.out.println(m.size()); // 3

	m.put(new a("mm", 29), 10000);
	m.put(new a("mm", 29), 20000);
	System.out.println(m); // {b=22, c=3, a=123, A [name=mm, age=29]=20000}

	m.remove("a");
	System.out.println(m); // {b=22, c=3, A [name=mm, age=29]=20000}

	System.out.println(m.get(new a("mm", 29))); // 20000
	System.out.println(m.get(new a("mam", 0))); // null

	Set set1 = m.keySet();
	Iterator i1 = set1.iterator();
	while (i1.hasNext()) {
		System.out.println(i1.next());
	}

	m.put(null, null);
	Collection c = m.values();
	Iterator i2 = c.iterator();
	while (i2.hasNext()) {
		System.out.println(i2.next());
	}

	Set set2 = m.entrySet();
	Iterator i3 = set2.iterator();
	while (i3.hasNext()) {
		System.out.println(i3.next());
	}

	System.out.println(set2); // [null=null, b=22, c=3, A [name=mm,
								// age=29]=20000]
}

/*
 * LinkedHashMap :使用链表,维护Map添加顺序
 */
@Test
public void test12() {
	Map m = new LinkedHashMap();
	m.put("a", 111);
	m.put("b", 22);
	m.put("c", 3);
	m.put("a", 123);
	m.put(new a("mm", 29), 10000);
	m.put(new a("mm", 29), 20000);
	m.put(null, null);

	Set set = m.entrySet();
	Iterator i = set.iterator();
	while (i.hasNext()) {
		System.out.println(i.next());
	}
}

/*
 * TreeSet:按照key排序 自然排序
 */
@Test
public void test13() {
	Map m = new TreeMap();
	m.put(new a("zhangs", 29), 10000);
	m.put(new a("lisi", 18), 20000);
	m.put(new a("wangwu", 31), 10000);
	m.put(new a("zhaoliu", 42), 20000);
	m.put(new a("lisi", 29), 20000);

	Set set = m.entrySet();
	Iterator i = set.iterator();
	while (i.hasNext()) {
		System.out.println(i.next());
	}
}

/*
 * TreeSet:按照key排序 定制排序
 */
@Test
public void test14() {
	Comparator c = new Comparator() {
		@Override
		public int compare(Object o1, Object o2) {
			if (o1 instanceof b && o2 instanceof b) {
				b b1 = (b) o1;
				b b2 = (b) o2;
				return b1.getName().compareTo(b2.getName()) == 0 ? b1
						.getAge().compareTo(b2.getAge()) : b1.getName()
						.compareTo(b2.getName());
			}
			return 0;
		}
	};

	Map m = new TreeMap(c);
	m.put(new b("zhangs", 23), 10000);
	m.put(new b("lisi", 20), 15000);
	m.put(new b("wangw", 33), 20000);
	m.put(new b("zhaoliu", 11), 15000);
	m.put(new b("sunq", 6), 30000);
	m.put(new b("wangw", 11), 100000);
	m.put(new b("wangw", 9), 20000);

	Set set = m.entrySet();
	Iterator i = set.iterator();
	while (i.hasNext()) {
		System.out.println(i.next());
	}
}

/*
 * Properties:常用来处理属性文件,key-value为String类型
 */
@Test
public void test15() throws FileNotFoundException, IOException {
	Properties p = new Properties();
	p.load(new FileInputStream(new File("src/package01/jdbc.properties")));
	System.out.println(p.getProperty("user")); // root
	System.out.println(p.getProperty("password")); // root
}

/*
 * Collections的集合工具类:Collection接口和Map接口 
 * 1、static void reverse(List<?> list):List反转
 * 
 *  2、static void shuffle(List<?> list) :List随机排序
 *  3、static <T extends
 * Comparable<? super T>> void sort(List<T> list) : List 排序
 *  4、static <T extends Object & Comparable<? super T>> T max(Collection<? extends T>
 * coll) :List求最大值 
 * 5、static <T> void copy(List<? super T> dest, List<?
 * extends T> src) : 复制
 * 6、static <T> List<T> synchronizedList(List<T> list)  :线程安全
 */
@Test
public void test16() {
	List l = new ArrayList();
	l.add(123);
	l.add(222);
	// l.add("abc");
	// l.add(new a("lisi", 23));
	l.add(333);

	System.out.println(l); // [123, 222, abc, A [name=lisi, age=23], 333]

	Collections.reverse(l);
	System.out.println(l); // [333, A [name=lisi, age=23], abc, 222, 123]

	Collections.shuffle(l);
	System.out.println(l); // [A [name=lisi, age=23], 333, abc, 123, 222]

	Collections.sort(l);
	System.out.println(l); // [123, 222, 333]

	System.out.println(Collections.max(l)); // 333

	l.add(222);
	l.add(222);
	System.out.println(Collections.frequency(l, 222)); // 3

	List l1 = Arrays.asList(new Object[l.size()]);
	Collections.copy(l1, l);
	System.out.println(l1); // [123, 222, 333, 222, 222]

	List l2 = Collections.synchronizedList(l);
	System.out.println(l2); //[123, 222, 333, 222, 222]
}


class b {
	private String name;
	private Integer age;

	public b() {
		super();
	}

	public b(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "b [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((age == null) ? 0 : age.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		b other = (b) obj;
		if (age == null) {
			if (other.age != null)
				return false;
		} else if (!age.equals(other.age))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}


class a implements Comparable{
	private String name ;
	private Integer age;

	public a() {
		super();
		System.out.println("空参");
	}

	public a(String name) {
		super();
		this.name = name;		
		System.out.println("有参");
	}

	public a(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		a other = (a) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "A [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int compareTo(Object o) {
		if (o instanceof a) {
			a a1 = (a)o;
			return this.name.compareTo(a1.name) == 0 ?  this.age.compareTo(a1.age) : this.name.compareTo(a1.name) ;
		}
		return 0;
	}
};