集合笔记(超详细)

课程内容

1、集合的概述
2、Collection
3、List
4、Arraylist、LinkedList、Vector
5、泛型
6、Set
7、Map
8、Collections工具类
9、斗地主的制牌、洗牌和发牌

集合的体系结构

1、集合分类:
 	单列集合:每个元素都是一个单独的个体
 	双列集合:每个操作都是针对一对数据来进行的,一对数据作为
 	一个单位
2、单列集合的体系:
 	Collection					单列集合的顶层接口
 	 	List						有序的子接口
 	 	 	ArrayList 	 	 	顺序存储,查询修改块
 	 	 	LinkedList				链式存储,增加删除块
 	 	 	Vector 	 	 	 	顺序存储,都慢
 	 	Set						无序的子接口
 	 	 	HashSet				哈希存储
 	 	 	 	LinkedHashSet
3、双列结合的体系:
 	Map							双列集合的顶层接口
 	 	HashMap 	 	 	 	哈希表存储
 	 	 	LinkedHashMap

Collection

1、单词:收集、集合
2、单列集合的顶层接口,定义的是所有单列集合中共有的功能。
3、Collection是一个接口,不能直接创建对象,随意找一个实现类
   创建对象
 	使用接口类型的引用,指向实现类的对象
 	Collection类型的引用,指向 ArrayList类型的对象(只能调
 	用接口中的方法)
4、常用方法:
 	add(Object obj):将obj元素添加到集合中
 	remove(Object obj):将obj元素从集合中删除
 	clear():将集合中的元素清空
 	isEmpty():判断集合是否为空
 	contains(Object obj):判断集合中是否包含obj元素
    size():返回集合中的元素个数

Collection的第一种遍历方式

1、转成数组,通过遍历数组的方式,来间接的遍历集合
2、Object[] toArray():将调用者集合转成Object类型的数组
package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.Collection;

public class Demo03_Collection的第一种遍历方式 {

	public static void main(String[] args) {
		Collection persons = new ArrayList();
		persons.add(new Person("zhangsan", 23));
		persons.add(new Person("lisi", 24));
		persons.add(new Person("wangwu", 25));
		persons.add(new Person("zhaoliu", 26));
		//转成Object数组
		Object[] objs = persons.toArray();
		//遍历数组
		for (int i = 0; i < objs.length; i++) {
			//由于在存储的时候,就提升成了Object类型,所以取
			出也是Object类型
			Object obj = objs[i];
			//向下转型,转型之后才能调用Person类中的方法
			Person p = (Person)obj;
			System.out.println(p.getName() + "..." +
			 p.getAge()); 
		}
	}

	private static void test1() {
		Collection c = new ArrayList();
		c.add(123);
		c.add(234);
		c.add(666);
		c.add("abc");
		c.add("xyz");
		
		//转成Object类型的数组
		Object[] objs = c.toArray();
		//通过遍历数组的方式,间接的遍历集合
		for (int i = 0; i < objs.length; i++) {
			System.out.println(objs[i]);
		}
	}
}

Collection中带all的方法

1、addAll(Collection c):将参数c中的所有元素,都添加到调用
   者集合中
2、removeAll(Collection c):从调用者集合中,删除那些也存在
   于参数c中的元素
3、containsAll(Collection c):判断调用者,是否能包含参数c中
   的所有元素
4、retainAll(Collection c):参数c中有哪些元素,就在调用者集
   合中,保留哪些元素(交集)

集合遍历的第二种方式:迭代器

1、迭代:更迭、更新换代,有从某一个到下一个的过程的含义

2、迭代器:专门用于将集合中的元素,一个到另一个逐个进行迭代的
   对象
   
3、获取:集合自己内部就应该有一个可以迭代自己的对象,从集合对
   象中获取即可
 	Iterator  iterator()
 	
4、迭代器的使用:
 	方法iterator返回的是一个Iterator接口的实现类对象,可以
 	使用的就是Iterator接口中的方法:
 	hasNext():判断集合中是否还有下一个元素
 	next():获取集合中的下一个元素
 	remove():删除迭代器对象正在迭代的那个对象
 	
5、迭代器的注意事项:

 	1、迭代器对象虽然多次调用next方法,都是同样的方法名称,
 	   但是每次调用返回的结果是不同的,会因为next方法既可以
 	   获取下一个元素,也会让迭代器对象,向前移动一步。
 	   
 	2、如果没有下一个元素,仍然调用next方法,出现           
 	   NoSuchElementException(没有当前元素异常),
 	   可以使用hasNext方法判断是否有下一个元素,
 	   决定是否调用next方法
 	   
 	3、hasNext方法,判断是否有下一个元素,不会移动迭代器位置
 	
 	4、next方法,不仅可以获取下一个元素,还会移动迭代器位置
 	
 	5、不要只判断一次hasNext,就调用多次next方法
package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Demo05_Collection的第二种遍历方式迭代器 {

	public static void main(String[] args) {
		Collection persons = new ArrayList();
		persons.add(new Person("zhangsan", 23));
		persons.add(new Person("lisi", 24));
		persons.add(new Person("wangwu", 25));
		persons.add(new Person("zhaoliu", 26));
		//获取迭代器对象
		Iterator it = persons.iterator();
		//反复判断是否有下一个元素(迭代器对象在不断的移动)
		while(it.hasNext()) {
	     	//获取下一个元素并且强转
			Person p = (Person)(it.next());
			
			System.out.println(p.getName() + "..." +
			 p.getAge());
		}
	}

	private static void test1_迭代器试用() {
		Collection c = new ArrayList();
		c.add(123);
		c.add(456);
		c.add(666);
		
		//获取集合的迭代器对象
		Iterator it = c.iterator();
		System.out.println(it.hasNext());
		System.out.println(it.next());
		System.out.println(it.hasNext());
		System.out.println(it.next());
		System.out.println(it.hasNext());
		System.out.println(it.next());
		System.out.println(it.hasNext());
		System.out.println(it.next());
	}
}

List

1、是Collection的一个子接口
2、特点:
 	有序:每个元素都有自己的位置,不同位置是有分别的
 	【有索引】:每个元素都有自己的编号
 	可以重复:即使是值相同的几个元素,位置和索引也各不相同,
 	可以区分这几个值。
3、特有方法:
 	add(int index, Object obj):在指定索引上,添加指定元素
 	remove(int index):删除指定索引上的值
 	set(int index, Object obj):将指定索引上的值,
 	修改为指定的值
 	get(int index):根据给定的索引,获取对应位置的值
package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.List;

public class Demo06_List特有方法 {

	public static void main(String[] args) {
		
	}

	private static void test1_List的特有方法() {
		List list = new ArrayList();
		list.add(0, "abc");
		list.add(0, "xyz");
		list.add(1, "666");
		System.out.println(list);
		
		list.remove(1);
		System.out.println(list);
		
		list.set(1, "def");
		System.out.println(list);
		
		System.out.println(list.get(0));
	}
}

第三种遍历方式

1、针对List集合特有的遍历方式
2、可以通过集合的size方法获取list集合索引的范围,根据索引
   通过get方法可以获取指定索引的值。
package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.List;

public class Demo07_第三种遍历方式 {

	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("abc");
		list.add("abc");
		list.add("abc");
		list.add("def");
		list.add("def");
		list.add("def");
		list.add("qq");
		for (int i = 0; i < list.size(); i++) {
			String str = (String)(list.get(i));
			System.out.println(str);
		}
	}
}

并发修改异常

1、ConcurrentModificationException
 	并发       修改      异常
 	
2、出现原因:
 	在使用【迭代器对象】遍历集合的同时,使用【集合对象】增加
 	集合的元素
 	
3、解决方法:两种解决方式都是针对List集合可以解决
 	方式1:迭代器遍历、迭代器增加
 	方式2:集合遍历、集合增加
 	
4、解决方式1:迭代器遍历、迭代器增加
 	迭代器遍历,和以前一样
 	迭代器增加:问题普通的迭代器中没有增加的方法,需要使用
 	List中特有的迭代器
 	列表迭代器:ListIterator,是Iterator的子接口,拥有
 	Iterator中的所有方法,还有特有
 	列表迭代器的获取:listIterator()
 	
5、解决方式2:集合遍历、集合添加
 	集合遍历:list特有的方式遍历,size和get方法结合
 	集合添加:集合的add方法
package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class Demo08_并发修改异常 {

	public static void main(String[] args) {
		List list = new ArrayList();
		list.add(111);
		list.add(111);
		list.add(222);
		list.add(333);
		list.add(444);
		list.add(555);
		list.add(555);
		
		test3_集合遍历集合添加(list);
		
	}

private static void test3_集合遍历集合添加(List list) {
		for(int i = 0; i < list.size(); i++) {
			Object obj = list.get(i);
			if (obj.equals(222)) {
				list.add(666);
			}
		}
		System.out.println(list);
	}

private static void test2_迭代器遍历迭代器添加(List list){
		//第一种解决思路:迭代器遍历,迭代器增加
		ListIterator lit = list.listIterator();
		while(lit.hasNext()) {
			Object obj = lit.next();
			if (obj.equals(222)) {
				lit.add(666);
			}
		}
		System.out.println(list);
	}

	private static void test1_并发修改异常(List list) {
		Iterator it = list.iterator();
		while(it.hasNext()) {
			Object obj = it.next();
			//判断如果这个数字是222,就在集合中添加一个666
			if (obj.equals(222)) {
//				list.add(666);
//				list.set(0, 666);
				list.remove(555);
			}
		}
		System.out.println(list);
	}

}

List的实现类

1、List只是一个接口,根据底层实现方式的不同,具有不同的实现类
2、ArrayList:数组实现,顺序存储
3、LinkedList:节点实现,链式存储
4、Vector:数组实现,顺序存储

ArrayList

1、也是List的一个实现类
2、没有什么特有方法
3、存储方式:
 	数组实现,顺序存储
 	通过物理内存的位置关系,来表达描述逻辑顺序的相邻

LinkedList

1、List的一个实现类

2、存储方式:
 	节点实现,链式存储
 	不通过物理内存位置的相邻,来表示逻辑顺序的相邻
 	每个元素都存储在一个节点中,节点除了元素数据本身以外,还
 	需要存储下一个元素的内存地址
 	
3、特点:
 	查询速度慢:需要根据前面的节点来获取后一个节点的地址,前
 	面所有节点都要访问一遍,节点数量越多,查询虚度越慢
 	增删速度快:增删一个元素,只需要修改新增元素前后的两个
 	节点的引用域即可,与集合本身的元素个数无关。
 	
4、LinkedList的特有方法:
 	由于在LinkedList中,维护了链表的头和尾节点的对象地址,
 	所以操作头部和尾部非常容易,提供了大量的操作头和尾的方法。
 	addFirst(Object obj):在头部添加元素
 	addLast(Object obj):在尾部添加元素
 	removeFirst():删除头部元素
 	removeLast():删除尾部元素
 	getFirst():获取头部元素
 	getLast():获取尾部元素

泛型

1、泛型:广泛的类型,在定义一个类的时候,类型中有些方法参数、
   返回值类型不确定,就使用一个符号,来表示那些尚未确定的类型
   ,这个符号,就称为泛型。
2、使用:对于有泛型的类型,在这些类型后面跟上尖括号,尖括号
   里面写上泛型的确定类型(在使用某个类创建对象时,已经可以
   确定这个具体的类型了,那么就直接写出具体类型)
   ArrayList al = new ArrayList();
3、泛型的好处:
 	1、提高了数据的安全性,将运行时的问题,提前暴露在编译时期
 	2、避免了强转的麻烦
4、注意事项: 
 	1、前后一致:在创建对象时,赋值符号前面和后面的类型的泛型
 	   ,必须一致
 	2、泛型推断:如果前面的引用所属的类型已经写好了泛型,后面
 	   创建对象的类型就可以只写一个尖括号,尖括号中可以不写任
 	   何内容。<>特别像菱形,称为“菱形泛型”,jdk1.7特性
package com.ujiuye.demos;

import java.util.ArrayList;

public class Demo01_泛型的使用和好处 {

	public static void main(String[] args) {
		ArrayList list = new ArrayList<>();
		list.add(111);
		list.add(222);
		list.add(666);
		list.add(888);
//		list.add("xyz");
		for (int i = 0; i < list.size(); i++) {
			int num = list.get(i);
			System.out.println(num);
		}
	}

	private static void test1_没有泛型的坏处() {
		ArrayList list = new ArrayList();
		list.add(111);
		list.add(222);
		list.add(666);
		list.add(333);
		list.add("abc");
		
		for (int i = 0; i < list.size(); i++) {
			Object obj = list.get(i);
			Integer it = (Integer)obj;
			System.out.println(it);
		}
	}
}

泛型类

1、泛型类:带着泛型定义的类
2、格式:
 	class 类名<泛型类型1, 泛型类型2, .....>  {

}
3、说明:
 	1、类名后面跟着的泛型类型,是泛型的声明,一旦泛型声明出来
 	   ,就相当于这个类型成为了已知类型,这个类型就可以在整个
 	   类中使用
 	2、泛型的声明名称,只需要是一个合法的标识符即可,但是通常
 	   我们使用单个大写字母来表示,常用字母:T、W、Q、K、V、E
 	3、泛型确定的时机:将来在使用和这个类,创建对象的时候

练习

1、定义一个带泛型的集合,只能在集合的头部进行增删
2、定义一个方法,可以交换任意类型的数组的某两个元素
package com.ujiuye.demos;

import java.util.LinkedList;

/**
 * 定义一个带泛型的集合,只能在集合的头部进行增删
 * 
 * d	c	b	a		栈		stack
 */
public class Demo03_泛型类定义练习 {

	public static void main(String[] args) {
		MyStack ms = new MyStack<>();
		ms.push("abc");
		ms.push("qq");
		ms.push("xyz");
		
		while(!ms.isEmpty()) {
		  String str = ms.pop();
		  System.out.print(str + "..." + str.length());
		}
	}
}

class MyStack {
	private LinkedList list = new LinkedList<>();
	
	//添加元素
	public void push(T t) {
		list.addFirst(t);
	}
	
	//删除元素
	public T pop() {
		return list.removeFirst();
	}
	
	//判断为空
	public boolean isEmpty() {
		return list.isEmpty();
	}
}
package com.ujiuye.demos;

import java.util.Arrays;

public class Demo04_泛型方法的定义 {

	public static void main(String[] args) {
		Integer[] arr = {1,2,3,4,5};
		System.out.println(Arrays.toString(arr));
		swap(arr, 0, 4);
		System.out.println(Arrays.toString(arr));
	}
	/**
	 * 交换任意类型的数组的某两个元素
	 */
	public static  void swap(T[] arr, int a, int b) {
		T temp = arr[a];
		arr[a] = arr[b];
		arr[b] = temp;
	}
}

泛型接口的定义和使用

1、带着泛型定义的接口,就是泛型接口
2、定义格式:
 	interface 接口名称<泛型类型1, 泛型类型2,...> {

}
3、说明:
 	1、在接口声明上,定义好的泛型,可以在整个接口中当做
 	   已知类型来使用
 	2、泛型接口被其他类实现的时候,有两种实现方式: 	 	
 	  1、声明的类不再是一个泛型类,而是一个确定了泛型的类,
 	 	格式如下: 	 	 	 	
 	 	class 实现类类名 implements 接口名<具体类型> {
 	 	 	 	所有的泛型类型都已经被确定
}
      2、声明的来还是一个泛型类,泛型的类型和接口的泛型一致,
 	 	格式如下:
 	 	 	class 实现类类名<泛型标识符1> implements
 	 	 	 接口名<泛型标识符1> {
  	 	 		所有的方法还都是可以使用泛型标识符的方法。
}
4、集合体系中,大量的接口和实现类都存在实现和继承的关系
 	Collection...继承关系...
 	List....实现关系....ArrayList
package com.ujiuye.demos;

public class Demo05_泛型接口的定义和使用 {

	public static void main(String[] args) {

	}

}

interface MyInter {
	public abstract T get();
	
	public abstract void use(T t);
}

class MyImpl4 implements MyInter {

	@Override
	public Integer get() {
		return null;
	}

	@Override
	public void use(Integer t) {
		System.out.println();
	}
	
}

class MyImpl3 implements MyInter {

	@Override
	public TW get() {
		return null;
	}

	@Override
	public void use(TW t) {
	}
	
}

class MyImpl2 implements MyInter {

	@Override
	public T get() {
		return null;
	}

	@Override
	public void use(T t) {
	}
	
}

class MyImpl1 implements MyInter {

	@Override
	public Integer get() {
		return new Integer(666);
	}

	@Override
	public void use(Integer t) {
		System.out.println(t.intValue());
	}
	
}

Set

1、Set是Collection的另一个子接口
2、特点:
 	无序:没有任何前后的分别,所有的元素没有位置的概念,所有
 	的元素都在集合中
 	没有索引:集合中没有任何位置,元素也就没有位置的属性
 	不能重复:没有位置的区分,相同值的元素没有任何分别,所以
 	不能重复
3、Set的实现类:
 	HashSet:使用哈希表的存储方式存储元素的Set集合
4、存储特点:
 	1、相同的元素无法存储进Set集合
 	2、集合本身不保证顺序:存储的顺序和取出的顺序不保证一致
package com.ujiuye.demos;

import java.util.HashSet;
import java.util.Set;

public class Demo07_Set {

	public static void main(String[] args) {
		Set set = new HashSet<>();
		set.add("abc");
		set.add("abc");
		set.add("abc");
		set.add("xyz");
		set.add("xyz");
		set.add("qq");
		set.add("qq");
		set.add("qq");
		System.out.println(set);
	}
}

Set集合的遍历

1、没有自己特有的方法,只能使用Collection接口中定义的方法,
   只能使用Collection的遍历方式
2、第一种:转成数组,toArray(),不带泛型的转数组,得到的是
   Object类型的数组。
3、第二种:转成数组,toArray(T[] arr),带泛型的转数组,得到
   的是T类型的数组。
 	1、自己创建的数组大小,小于集合元素个数
 	 	在方法中,就只能创建一个新的数组,使用集合元素将数组
 	 	填充,将新数组返回
 	2、自己创建的数组大小,等于集合元素个数
 	  	在方法中,就不需要创建新的数组,使用集合元素将传入的
 	  	数组填充,将原数组返回
 	3、自己创建的数组大小,大于集合元素个数
 	 	在方法中,也不创建新的数组,直接将传入的数组前面几个
 	 	位置填充,为集合的元素,剩余位置使用null填充
 	 	(默认值就是null)
4、第三种:迭代器
5、第四种:增强for循环
 	格式:
 	 	for (元素的数据类型 元素名称 : 要遍历的集合) {
 	 	 	使用元素名称代表当前访问的元素
} 
 	说明:
 	 	元素的数据类型,值得是要遍历的集合中的元素的数据类型
 	 	元素名称虽然是固定的,但是随着循环的执行,每次代表的
 	 	元素却不相同
 	 	要遍历的集合,单列集合或者是数组
 	本质:
 	 	底层还是迭代器,只不过使用这种格式更加简洁
 	注意事项:
 	 	使用增强for,没有拿到元素的索引,无法修改集合或者
 	 	数组中的元素值
 	 	底层是迭代器,所以在遍历的时候,使用集合对象增加元素
 	 	,会发生并发修改异常
package com.ujiuye.demos;

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

public class Demo09_使用迭代器遍历set集合 {

	public static void main(String[] args) {
		Set set = new HashSet<>();
		set.add("abc");
		set.add("aa");
		set.add("bb");
		set.add("cc");
		set.add("qq");
		set.add("xyz");
		
		Iterator it = set.iterator();
		while(it.hasNext()) {
			String str = it.next();
			System.out.print(str + " ");
		}
	}
}
package com.ujiuye.demos;

import java.util.HashSet;
import java.util.Set;

public class Demo10_增强for循环 {

	public static void main(String[] args) {
		Set set = new HashSet<>();
		set.add("abc");
		set.add("aa");
		set.add("bb");
		set.add("cc");
		set.add("qq");
		set.add("xyz");
		
		for (String str : set) {
			System.out.print(str + " ");
		}
		System.out.println();
		
		int[] arr = {23, 45, 56, 666, 888};
		for (int i : arr) {
			System.out.print(i + " ");
		}
	}
}

练习

随机生成10个20~40之间的随机数,存储在合适的集合中,并且进行
遍历,要求:随机数不能重复0
键盘录入一个字符串,输出其中的字符,相同字符只输出一次
package com.ujiuye.demos;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class Demo11_Set练习1 {
	/**
	 * 随机生成10个20~40之间的随机数,存储在合适的集合中
	   ,并且进行遍历,要求:随机数不能重复0
	 */
	public static void main(String[] args) {
		Random rd = new Random();
		Set nums = new HashSet<>();
		while(nums.size() < 10) {
			//生成一个20-40的随机数
			int x = rd.nextInt(21) + 20;
			//添加到nums集合中去
			nums.add(x);
		}
		
//		for (int i : nums) {
//			System.out.print(i + " ");
//		}
		
	//使用fore alt + /快速生成最近的数组的增强for循环格式
	}
}
package com.ujiuye.demos;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Demo12_set练习2去重 {
	/**
	 * 键盘录入一个字符串,输出其中的字符,相同字符只输出一次
	 */
	public static void main(String[] args) {
		Set set = new HashSet<>();
		Scanner sc = new Scanner(System.in);
		System.out.println("请录入一个字符串");
		String line = sc.nextLine();
		//1、转成字符数组
		char[] arr = line.toCharArray();
		//2、遍历数组,获取每个字符
		for (char c : arr) {
			//3、将字符添加到合适的集合中,完成去重
			set.add(c);
		}
		//4、将集合遍历输出每个字符
		for (char c : set) {
			System.out.print(c + " ");
		}
	}

}

HashSet保证元素唯一性原理的总结

1、某个对象obj,在即将要存储到HashSet集合的时候,首先计算obj
   的hashCode值
   
2、在集合中的所有元素的哈希值,都和obj的哈希值不同,说明在
   集合中不存在obj,可以直接将obj存储到HashSet中
   
3、在集合中有若干元素的哈希值,和obj的哈希值相同,并不能说明
   obj已经存在于集合中,需要使用equals判断obj是否和那些与自
   己哈希值相同的元素是否相等
   
4、如果这些元素所有的和obj比较equals之后,都不相等,那么就
   说明obj不存在于集合中,可以将obj存储到HashSet中
   
5、如果这些元素有任意一个和obj比较equals之后,发现相等,那
   么就说明obj已经存在于集合中,所以obj就不能存储,存储失败。

保证元素唯一性的操作

1、重写hashCode
 	相同的对象,一定要有相同的哈希值
 	不同的对象,尽量有不同的哈希值
 	操作:根据对象的属性来生成哈希值
2、重写equals方法:
 	比较的就是各个对象的属性值,是否全都相同
3、最终操作:
 	使用快捷键,直接全部生成:alt + shift + s	h
package com.ujiuye.demos;

public class Person {
	private String name;
	private int age;
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age 
		+ "]";
	}
//	@Override
//	public boolean equals(Object obj) {
//  System.out.println("Person类的equals方法被调用了");
//		Person other = (Person)obj;
//		return this.name.equals(other.name) && this.age 
        == other.age;
//	}
//	@Override
//	public int hashCode() {
//		return age + name.hashCode();
//	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		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;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}

LinkedHashSet

1、是HashSet的一个子类,和HashSet保证元素唯一的原理相同。
2、将每个元素在存储的时候,都记录了前后元素的地址
3、效果:
 	可以根据存储元素的顺序,将元素取出
4、应用:
 	既需要保证元素的唯一,又需要保证原来的顺序,就可以考虑
 	LinkedHashSet类型
package com.ujiuye.demos;

import java.util.LinkedHashSet;

public class Demo15_LinkedHashSet {
	public static void main(String[] args) {
		LinkedHashSet lhs = new LinkedHashSet();
		lhs.add("abc");
		lhs.add("abc");
		lhs.add("abc");
		
		lhs.add("xyz");
		lhs.add("xyz");
		
		lhs.add("qq");
		
		lhs.add("123");
		lhs.add("123");
		lhs.add("123");
		System.out.println(lhs);
	}
}

Map

1、Map:双列集合的顶层接口

2、Map:单词含义,地图,地图上的每个点,都表示了生活中的一个
   具体位置。地图的点和生活中的位置,有一个一一对应的关系,
   这种关系是通过穷举的方式来描述的。
   
3、Map:描述的就是一个数据(key)到另一个数据(value)的映射
   关系(对应关系)
 	一个数据(key):就是有规律的,容易记忆的,简单的一个数据
 	另一个数据(value):没有规律的,不容易记忆的,复杂的一个
 	数据
 	大多数都是根据key来寻找value
 	
4、映射:对应关系
 	表达式方式:y = x * x
 	穷举罗列:{1=1, 2=4, 3=9, 4=16, 5=25}
 	
5、java中Map就是使用的穷举罗列的方式来描述映射关系

6、Map的特点:
 	Key(键)是唯一的,value(值)不是唯一的
 	每个键都只能对应确定唯一的值
 	
7、Map和Collection的区别:
 	Map是双列集合,Collection是单列集合
 	Map的键是唯一的,Collection中的Set子接口中的元素是唯一的
 	Map的所有操作和算法都是针对键有效,Collection中的set子
 	接口中的操作和算法针对元素有效

Map中的常用方法

1、增加键值对:put(K key, V value)
2、删除方法:
 	根据给定的键,删除对应的键值对:remove(K key)
 	清空集合:clear()
3、获取方法:
 	获取集合的大小:size(),获取键值对对数
 	根据给定的键,获取对应的值:V get(K key)
4、判断方法:
 	判断集合中是否存在某个键:containsKey(Object obj)
 	判断集合中是否存在某个值:containsValue(Object obj)
5、修改方法:
 	根据给定的键,修改对应的值:put(K key, V value)
 	如果在集合中已经存在key这个键,那么使用put方法,就是修改
 	其对应的值;如果集合中不存在key这个键,那么使用put方法,
 	就是在集合中增加了一个键值对
package com.ujiuye.demos;

import java.util.HashMap;
import java.util.Map;

public class Demo01_Map的常用方法 {

	public static void main(String[] args) {
		//创建实现类对象
		Map map = new HashMap<>();
		//添加键值对
		map.put("abc", 3);
		map.put("xyz", 3);
		map.put("qq", 2);
		map.put("qwer", 4);
		//获取abc键对应的值
		int count = map.get("abc");
		//打印集合内容,获取集合大小
		System.out.println(map + "..." + map.size() +
		 "..." + count);
		//判断集合是否存在abc键
		System.out.println(map.containsKey("abc"));
		//修改abc键对应的值
		map.put("abc", 666);
		System.out.println(map);
		//删除abc对应的键值对
		map.remove("abc");
		System.out.println(map + "..." + map.size() +
		 "..." +  map.get("abc"));
		System.out.println(map.containsKey("abc"));
		map.clear();
		System.out.println(map + "..." + map.size());
	}
}

Map集合的第一种遍历思路

package com.ujiuye.demos;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo02_Map的第一种遍历思路 {

	public static void main(String[] args) {
		Map map = new HashMap<>();
		map.put("abc", 3);
		map.put("qq", 2);
		map.put("xyz", 3);
		map.put("qwer", 4);
		
		test2_第一种遍历思路的第二种遍历方式增强for(map);
	}

	private static void test2_第一种遍历思路的第二种遍历
	方式增强for(Map map) {
		//获取所有键的Set集合
		for (String key : map.keySet()) {
			System.out.println(key + "..." +
			 map.get(key));
		}
	}

	private static void test1_第一种遍历思路下的第一种遍历
	方式迭代器(Map map) {
		Set keys = map.keySet();
		
		//获取用于遍历keys这个集合的迭代器对象
		Iterator it = keys.iterator();
		
		//使用迭代器遍历
		while(it.hasNext()) {
			String key = it.next();
			
			//根据键来获取对应的值
			int value = map.get(key);
			System.out.println(key + "..." + value);
		}
	}
}

Map集合的第二种遍历思路

package com.ujiuye.demos;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo03_Map的第二种遍历思路 {

	public static void main(String[] args) {
		Map map = new HashMap<>();
		map.put("abc", 3);
		map.put("qq", 2);
		map.put("xyz", 3);
		map.put("qwer", 4);
		
		test2_增强for循环遍历Set(map);
	}

	private static void test2_增强for循环遍历Set
	(Map map) {
		for (Map.Entry en : 
		map.entrySet()) {
			System.out.println(en.getKey() + "..." +
			en.getValue());
		}
	}

	private static void test1_迭代器遍历Set集合
	(Map map) {
	
		//获取Map集合中的所有键值对对象的Set集合
		Set> entrys = 
		map.entrySet();
		
		//遍历Set,使用迭代器
		Iterator> it = 
		entrys.iterator();
		
		//使用迭代器遍历Set集合
		while(it.hasNext()) {
			//获取Set集合中的每个Entry对象
			Map.Entry en = it.next();
			//获取Entry对象中的键
			String key = en.getKey();
			//获取Entry对象中的值
			int value = en.getValue();
			System.out.println(key + "..." + value);
		}
		
	}

}

练习

键盘录入一个字符串,统计每个字符出现的次数
例如,录入aaaabbccddd!@#@#$@#$%cc66ff
打印出来:a有3个,b有2个,c有4个,d有3个,!有1个,@有3个,
$有2个,%有1个,6有2个,f有2个
package com.ujiuye.demos;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * 键盘录入一个字符串,统计每个字符出现的次数
	例如,录入aaaabbccddd!@#@#$@#$%cc66ff
	打印出来:a有4个,b有2个,c有4个,d有3个,!有1个,@有3个,$有2个,%有1个,6有2个,f有2个
 * @author Administrator
 *
 */
public class Demo04_Map练习统计字符 {

	public static void main(String[] args) {
		Map map = new HashMap<>();
		Scanner sc = new Scanner(System.in);
		System.out.println("请录入一个字符串");
		String line = sc.nextLine();
		/**
		 * 根据要统计的结果发现:其实统计的是字符和次数的对应关系,所以使用Map集合
		 * 判断当前集合中是否有某个字符
		 *  	如果没有,就把这个字符和1作为键和值存储到集合中
		 *  	如果有,就把这个字符对应的值,加一
		 */
		//获取字符串的字符数组
		char[] chs = line.toCharArray();
		//遍历数组
		for (char c : chs) {
//			//判断当前字符是否存在于集合的键中,如果存在
//			if (map.containsKey(c)) {
//				//先把之前的字符的次数取出
//				int count = map.get(c);
//				//加一之后,再存回去
//				map.put(c, count+1);
//			} else {
//				//如果当前字符不存在于集合的键中,说明之前没有统计过
//				map.put(c, 1);
//			}
			map.put(c, map.containsKey(c) ? map.get(c) + 1 : 1 );
		}

		//准备拼接结果的字符串
		StringBuilder sb = new StringBuilder();
		//通过增强for遍历map,并且拼接
		for (Map.Entry en : map.entrySet()) {
			//a有4个,
			sb.append(en.getKey()).append("有").append(en.getValue()).append("个,");
		}
		//取得拼接结果的一部分(最后一个逗号不要)
		System.out.println(sb.substring(0, sb.length()-1));
	}
}

HashMap

1、就是Map集合使用哈希表的存储方式的一种实现类 

2、HashMap存储的是jdk中提供的类型的键,
   就可以直接保证键的唯一性
   
3、HashMap中存储的键,是自定义类型,无法保证键的唯一性;
   原因:虽然都是张三、23,但是这些对象并不是相同的对象,
   这些对象的哈希值计算结果各不相同,就说明一定不是相同的对象
   ,所以无法保证键的唯一。重写hashCode和equals方法
 	说明:HashMap的键的唯一性和HashSet的元素的唯一性,
 	保证方式都一样
 	
4、HashMap和HashSet的关系:
 	1、HashSet是由HashMap实现出来的,HashSet就是HashMap的
 	键的那一列
 	2、将HashMap中的值的那一列隐藏掉,就变成了HashSet
package com.ujiuye.demos;

import java.util.HashMap;

public class Demo05_HashMap {

	public static void main(String[] args) {
		HashMap hm = new HashMap<>();
		hm.put(new Person("张三", 23), "bj");
		hm.put(new Person("张三", 23), "sh");
		hm.put(new Person("张三", 23), "gz");
		hm.put(new Person("张三", 23), "sz");
		System.out.println(hm);
	}

	private static void test1_HashMap存储jdk的键() {
		HashMap hm = new HashMap<>();
		hm.put("abc", 1);
		hm.put("abc", 2);
		hm.put("abc", 3);
		hm.put("abc", 4);
		System.out.println(hm);
	}
}
package com.ujiuye.demos;

public class Person {
	private String name;
	private int age;
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		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;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}

LinkedHashMap

1、是HashMap的一个子类
2、和HashMap的不同之处在于,具有可预知的迭代顺序,
   存储键值对的顺序和遍历集合时取出键值对的顺序一致。
package com.ujiuye.demos;

import java.util.LinkedHashMap;

public class Demo06_LinkedHashMap {

	public static void main(String[] args) {
		LinkedHashMap lhm = new LinkedHashMap<>();
		lhm.put("abc", 3);
		lhm.put("xyz", 3);
		lhm.put("qq", 2);
		lhm.put("qwer", 4);
		System.out.println(lhm);
	}
}

HashMap和Hashtable的关系

1、HashMap和Hashtable都是用于存储键和值的对应关系,
   都是Map的实现类,都是使用哈希表的方式存储。
2、不同点:
 	1、版本不同,Hashtable是jdk1.0版本出现的,
 	   HashMap是jdk1.2版本出现的
 	2、线程安全性不同,Hashtable是线程安全的,
 	   HashMap是线程不安全的
 	3、Hashtable不能存储null键null值,
 	   HashMap可以存储null键null值
 	4、命名规则:Hashtable时期没有形成完全严格的命名要求

Collections工具类

1、int  binarySearch(List list, E e ):
   在一个有升序顺序的List集合中,通过二分查找寻找元素e的索引
   
2、fill(List list, E e):
   将list集合中的所有元素都填充为元素e
   
3、int frequency(Collection c, E e):
   返回在集合c中的元素e的个数

4、max、min:
   获取集合的最大值或者最小值

5、replaceAll(List list, E oldVal, E newVal):
   将集合list中的所有指定老元素oldVal都替换成新元素newVal

6、reverse(List list):
   将参数集合list进行反转

7、shuffle(List list):
   将list集合中的元素进行随机置换

8、swap(List list, int a, int b):
   将a索引和b索引的元素进行交换

9、synchronizedXxx方法系列:
   将一个线程不安全的集合传入方法,返回一个线程安全的集合
package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.Collections;

public class Demo08_Collections工具类 {

	public static void main(String[] args) {
		ArrayList list= new ArrayList<>();
		list.add(10);
		list.add(22);
		list.add(44);
		list.add(666);
		list.add(888);
		list.add(999);
		//获取集合的最大值
		System.out.println(Collections.max(list));
		//通过二分查找,找到888元素的索引
		System.out.println(Collections.binarySearch(list, 888));
		Collections.reverse(list);
		System.out.println(list);
		//将集合list中的所有元素,都填充为66
		Collections.fill(list, 66);
		System.out.println(list);
		//统计66在list集合中出现的次数
		System.out.println(Collections.frequency(list, 66));
		//将集合list中的所有66都替换成666
		Collections.replaceAll(list, 66, 666);
		System.out.println(list);
		//将集合元素顺序全部打乱
		Collections.shuffle(list);
		System.out.println(list);
		//交换0和3索引对应的元素
		Collections.swap(list, 0, 3);
		System.out.println(list);
		//将集合进行排序(升序排序)
		Collections.sort(list);
		System.out.println(list);
	}
}
1、思路:
 	1、制牌:1~K一共13个数字,四个花色,
 	   4 * 13张牌,小王、大王 
 	   
 	2、洗牌:shuffle将集合中的字符串随机置换
 	
 	3、发牌:将一个集合中的元素,分发到3个集合中
 	
2、问题:

 	发牌之后,每个人的牌都没有顺序,无法洗牌,
 	字符串的字典顺序,和扑克牌中的大小顺序不同,
 	不能使用字典顺序来直接排序
 	
3、解决:

 	1、通过穷举,手动将所有牌面的大小,全都定义出来,
 	   每个牌面上的字符串,
 	   都可以对应一个其在扑克牌中的大小的数字
 	   (字符串和数字的对应关系)
 	   
 	2、可以给牌面的大小排序,对应到某个牌面
package com.ujiuye.demos;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

public class Demo10_斗地主的制牌洗牌和发牌有顺序 {

	public static void main(String[] args) {
		//制牌
		String[] colors = {"黑桃", "红桃", "梅花", "方片"};
		String[] nums = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
		HashMap table = new HashMap<>();
		ArrayList pokers = new ArrayList<>();
		int power = 0;
		for (String num : nums) {
			for (String color : colors) {
				table.put(power, color + num);
				pokers.add(power);
				power++;
			}
		}
		table.put(power, "小王");
		pokers.add(power++);
		table.put(power, "大王");
		pokers.add(power);
		System.out.println(table);
		System.out.println(pokers);
		
		
		//洗牌
		Collections.shuffle(pokers);
		System.out.println(pokers);
		
		//发牌
		//准备四个玩家集合
		ArrayList dipai = new ArrayList<>();
		for (int i = 1; i <= 3; i++) {
			dipai.add(pokers.remove(0));
		}
		ArrayList xiaoDao = new ArrayList<>();
		ArrayList longwu = new ArrayList<>();
		ArrayList me = new ArrayList<>();
		//给从牌中拿出第一章牌发给某个玩家
		while(true) {
			//如果还有拍,就发
			if (!pokers.isEmpty()) {
				xiaoDao.add(pokers.remove(0));
			}
			if (!pokers.isEmpty()) {
				longwu.add(pokers.remove(0));
			}
			if (!pokers.isEmpty()) {
				me.add(pokers.remove(0));
			} else {//如果没有牌了,就结束发牌
				break;
			}
		}
		
		//每个玩家分别洗牌
		Collections.sort(dipai);
		Collections.sort(xiaoDao);
		Collections.sort(longwu);
		Collections.sort(me);
		
		//看牌
		System.out.println("底牌:" + kanPai(dipai, table));
		System.out.println("xiaoDao:" + kanPai(xiaoDao, table));
		System.out.println("longwu:" + kanPai(longwu, table));
		System.out.println("me:" + kanPai(me, table));
	}
	
	public static String kanPai(ArrayList pokers, HashMap table) {
		StringBuilder sb = new StringBuilder("[");
		for (int i : pokers) {
			String str = table.get(i);
			sb.append(str).append(", ");
		}
		return sb.replace(sb.length() - 1, sb.length(), "]").toString();
	}
}

作业

1.分析以下需求,并用代码实现:
	(1)有如下代码:
		List list = new ArrayList<>();
		
		list.add("a");
		list.add("a");
		list.add("a");
		list.add("b");
		list.add("b");
		list.add("c");
		list.add("d");
		list.add("d");
		list.add("d");
		list.add("d");
		list.add("d");
		
		System.out.println(frequency(list, "a"));	// 3
		System.out.println(frequency(list, "b"));	// 2
		System.out.println(frequency(list, "c"));	// 1
		System.out.println(frequency(list, "d"));	// 5
		System.out.println(frequency(list, "xxx"));	// 0
	(2)定义方法统计集合中指定元素出现的次数,
	   如"a" 3,"b" 2,"c" 1
		 
2.分析以下需求,并用代码实现:
	(1)生成10个1至100之间的随机整数(不能重复),
	   存入一个List集合
	(2)编写方法对List集合进行排序
	(2)然后利用迭代器遍历集合元素并输出
	(3)如:15 18 20 40 46 60 65 70 75 91
	
3.分析以下需求,并用代码实现:
	(1)定义List集合,存入多个字符串,其中包含三个连续的"def"
	(2)删除集合中字符串"def"
	(3)然后利用迭代器遍历集合元素并输出
	
4.分析以下需求,并用代码实现:
	(1)定义List集合,存入多个字符串
	(2)删除集合中包含0-9数字的字符串
	(只要字符串中包含0-9中的任意一个就需要删除此整个字符串)
	(3)然后利用迭代器遍历集合元素并输出
	
5.使用LinkedHashSet类型完成如下需求:
	定义一个方法,可以对List集合内容进行去重,
	并且不改变原来List中元素的顺序
	
6.分析以下需求,并用代码实现:
	(1)定义一个学生类Student,
	   包含属性:姓名(String name)、年龄(int age)
	(2)定义Map集合,用Student对象作为key,
	   用字符串(此表示表示学生的住址)作为value
	(3)利用四种方式遍历Map集合中的内容,格式:key::value
	
7.分析以下需求,并用代码实现:
	(1)利用键盘录入,输入一个字符串
	(2)统计该字符串中各个字符的数量
	(3)如:
		用户输入字符串
		"If~you-want~to~change-your_fate_I_think~you~
		must~come-to-the-ujiuye-to-learn-java"
		程序输出结果:-(9)I(2)_(3)a(7)c(2)d(1).....
	
8.分析以下需求,并用代码实现:

	(1)统计每个单词出现的次数
	
	(2)有如下字符串
	"If you want to change your fate I think you must
	 come to the ujiuye to learn java"(用空格间隔)
	 
	(3)打印格式:
		to=3
  		think=1
  		you=2
  		//........

package 集合练习;

import java.util.ArrayList;
import java.util.List;

/*1.分析以下需求,并用代码实现:
(1)有如下代码:
	List list = new ArrayList<>();
	
	list.add("a");
	list.add("a");
	list.add("a");
	list.add("b");
	list.add("b");
	list.add("c");
	list.add("d");
	list.add("d");
	list.add("d");
	list.add("d");
	list.add("d");
	
	System.out.println(frequency(list, "a"));	// 3
	System.out.println(frequency(list, "b"));	// 2
	System.out.println(frequency(list, "c"));	// 1
	System.out.println(frequency(list, "d"));	// 5
	System.out.println(frequency(list, "xxx"));	// 0
	
(2)定义方法统计集合中指定元素出现的次数,如"a" 3,"b" 2,"c" 1
*/

public class Demo01 {
	public static void main(String[] args) {
		List list = new ArrayList<>();

		list.add("a");
		list.add("a");
		list.add("a");
		list.add("b");
		list.add("b");
		list.add("c");
		list.add("d");
		list.add("d");
		list.add("d");
		list.add("d");
		list.add("d");

		System.out.println(frequency(list, "a")); // 3
		System.out.println(frequency(list, "b")); // 2
		System.out.println(frequency(list, "c")); // 1
		System.out.println(frequency(list, "d")); // 5
		System.out.println(frequency(list, "xxx")); // 0
	}

	private static int frequency(List list, String str) {
		int count = 0;
		for (String s : list) {
			if (str.equals(s)) {
				count++;
			}
		}
		return count;
	}
}

第二题
package 集合练习;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*
	 2.分析以下需求,并用代码实现:
	(1)生成10个1至100之间的随机整数(不能重复),存入一个List集合
	(2)编写方法对List集合
	进行排序
	(2)然后利用迭代器遍历集合元素并输出
	(3)如:15 18 20 40 46 60 65 70 75 91
*/

public class Demo02 {
	public static void main(String[] args) {
		List list = new ArrayList();

		random(list);
		show(list);
		// System.out.println(list);
		sort(list);
		show(list);

	}

	private static void sort(List list) {
		for (int i = 0; i < list.size(); i++) {
			for (int j = 0; j < list.size() - i - 1; j++) {
				int a = list.get(j);
				int b = list.get(j + 1);
				if (a > b) {
					int temp = a;
					a = b;
					b = temp;
					list.set(j, a);
					list.set(j + 1, b);
				}

			}
		}
	}

	private static void show(List list) {
		// 遍历集合
		Iterator it = list.iterator();
		while (it.hasNext()) {
			int i = it.next();
			System.out.print(i + " ");
		}
		System.out.println();
	}

	private static void random(List list) {
		for (int i = 0; i < 10; i++) {
			int num = (int) (Math.random() * 100) + 1;
			list.add(num);
		}
	}
}

第三题
package 集合练习;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*
	 3.分析以下需求,并用代码实现:
	(1)定义List集合,存入多个字符串,其中包含三个连续的"def"
	(2)删除集合中字符串"def"
	(3)然后利用迭代器遍历集合元素并输出
*/
public class Demo03 {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("def");
		list.add("def");
		list.add("def");
		list.add("list");
		list.add("list");
		list.add("list");
		show(list);
		del(list);

		show(list);
	}

	private static void del(List list) {
		for (int i = 0; i < list.size(); i++) {
			if ("def".equals(list.get(i))) {
				list.remove(i);
				i--;
			}
		}
	}

	private static void show(List list) {
		Iterator it = list.iterator();
		while (it.hasNext()) {
			String s = it.next();
			System.out.print(s + " ");
		}
		System.out.println();
	}
}

第四题
package 集合练习;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*	
    4.分析以下需求,并用代码实现:
	(1)定义List集合,存入多个字符串
	(2)删除集合中包含0-9数字的字符串(只要字符串中包含0-9中的任意一个数字就需要删除此整个字符串)
	(3)然后利用迭代器遍历集合元素并输出
	*/
public class Demo04 {
	public static void main(String[] args) {
		List list = new ArrayList();
		for (int i = 0; i < 5; i++) {
			list.add(random(5));
		}
		System.out.println(list);
		del(list);
		Iterator it = list.iterator();
		while (it.hasNext()) {
			String str = (String) it.next();
			System.out.print(str + " ");
		}
		System.out.println();

	}

	// 删除包含0-9的字符串
	private static void del(List list) {
		for (int i = 0; i < list.size(); i++) {
			char[] cs = list.get(i).toCharArray();
			for (int j = 0; j < cs.length; j++) {
				if (cs[j] >= '0' && cs[j] <= '9') {
					list.remove(i);
					i--;
				}
			}
		}
	}

	// 随机填充
	private static String random(int num) {
		// 随机产生字符串填充
		String str = "";
		for (int i = '0'; i <= '9'; i++) {
			str += (char) i;
		}
		for (int i = 'a'; i <= 'z'; i++) {
			str += (char) i;
		}
		for (int i = 'A'; i <= 'Z'; i++) {
			str += (char) i;
		}

		char[] cs = new char[num];
		for (int i = 0; i < cs.length; i++) {
			int index = (int) (Math.random() * str.length()) + 1;
			cs[i] = str.charAt(index);
		}
//		String str2 = cs.toString();  这个要转为字符串必须要重写toString方法

		String str1 = new String(cs); // 正版方法
		return str1;
	}
}

第五题
package 集合练习;
//1、使用LinkedHashSet类型完成如下需求:

//定义一个方法,可以对List集合内容进行去重,并且不改变原来List中元素的顺序

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class Demo05 {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("def");
		list.add("def");
		list.add("def");
		list.add("list");
		list.add("list");
		list.add("list");
		System.out.println(list);

		Set set = new LinkedHashSet();
		set.addAll(list);
		System.out.println(set);
		System.out.println();
		for (String str : set) {
			System.out.print(str + " ");
		}

	}
}

第六题
package 集合练习;

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

/*	1.分析以下需求,并用代码实现:
	(1)定义一个学生类Student,包含属性:姓名(String name)、年龄(int age)
	(2)定义Map集合,用Student对象作为key,用字符串(此表示表示学生的住址)作为value
	(3)利用四种方式遍历Map集合中的内容,格式:key::value
*/

public class Demo06 {
	public static void main(String[] args) {
		Student s1 = new Student("张三", 18);
		Student s2 = new Student("李四", 18);
		Student s3 = new Student("王五", 18);
		
		Map map = new HashMap();
		map.put(s1, "北京");
		map.put(s2, "上海");
		map.put(s3, "东北");
		map.put(s3, "东北");

		metho01(map); // 增强for

		metho02(map); // 迭代器
	}

	private static void metho02(Map map) {
		Iterator> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = it.next();
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}
	}

	private static void metho01(Map map) {
		for (Student s : map.keySet()) {
			System.out.println(s + ":" + map.get(s));
		}
	}
}

class Student {

	String name;
	int age;

	public Student() {
		super();
	}

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

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

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		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;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

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

}
第七题
package 集合练习;

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

/*	2.分析以下需求,并用代码实现:
	(1)利用键盘录入,输入一个字符串
	(2)统计该字符串中各个字符的数量
	(3)如:
		用户输入字符串"If~you-want~to~change-your_fate_I_think~you~must~come-to-the-ujiuye-to-learn-java"
		程序输出结果:-(9)I(2)_(3)a(7)c(2)d(1).....
*/
public class Demo07 {
	public static void main(String[] args) {
		// 录入你吗啊!!不录
		String str = "If~you-want~to~change-your_fate_I_think~you~must~come-to-the-ujiuye-to-learn-java";

		char[] cs = str.toCharArray();
		Map map = new HashMap();
		for (int i = 0; i < cs.length; i++) {
			map.put(cs[i], map.containsKey(cs[i]) ? map.get(cs[i]) + 1 : 1);
		}


		Iterator> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = it.next();
			System.out.print(entry.getKey() + "(" + entry.getValue() + ")");

		}

	}
}

第八题
package 集合练习;

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

/*3.分析以下需求,并用代码实现:
(1)统计每个单词出现的次数
(2)有如下字符串"If you want to change your fate I think you must come to the ujiuye to learn java"(用空格间隔)
(3)打印格式:
	to=3
		think=1
		you=2
		//........
*/
public class Demo08 {
	public static void main(String[] args) {
		String str = "If you want to change your fate I think you must come to the ujiuye to learn java";
		Map map = new HashMap();
		
		String[] s = str.split(" ");
		for (String str1 : s) {
			map.put(str1, map.containsKey(str1) ? map.get(str1) + 1 : 1);
		}

		Iterator> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry en = it.next();
			System.out.println(en.getKey() + "=" + en.getValue());
		}
	}
}

你可能感兴趣的:(Java集合练习题)