返回顶部
扩大
缩小

Heaton

第九章 集合

9、java集合(3天)
9.1 Java集合框架 1课时
9.2 Collection接口API 1课时
9.3 Iterator迭代器接口 1课时
9.4 Collection子接口之一: List接口 1课时
9.5 Collection子接口之二:Set接口 1课时
9.6 Map接口 1课时
9.7 Collections工具类 1课时
##9-1 Java集合框架 #####Java 集合概述 + 一方面, 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另一方面,使用Array存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引用放入容器中。 + Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组。

案例

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.junit.Test;

/**
 * 1.java中的容器--在内存层面,对数据进行统一的存储和管理:数组 ; java集合
 *   拓展:数据的持久化:文件(.jpg;mp3等); xml; 数据库
 * 
 * 2. 数组在内存存储方面的特点:①数组初始化以后,长度就确定了。
 *                        ②数组声明的类型,就决定了进行元素初始化时的类型
 * 					   弊端:数组初始化以后,长度就不可变了。
 * 						    数组中提供的属性和方法少,不便于进行添加、删除、插入等操作
 * 						    数组存储的数据是有序的、可以重复的。---->存储数据的特点单一
 * 
 * 		String[] arr = new String[10];
 * 		Object[] 
 * 
 * 3.集合框架
		两者是并列关系
 *   java.util.Collection:单列数据
 *   	|------List子接口:存储有序的、可重复的数据 ---->"动态"数组
 *   		
 *   	|------Set子接口:存储无序的、不可重复的数据 ----->高中讲的"集合"
 *   		
 *   
 *   java.util.Map:双列数据。存储一对一对的数据:key-value对 ---->中学讲的"函数": y = f(x).  比如:y = x + 2;
 *                                                                    (x1,y1),(x2,y2),...
 * 
 * 4. 测试Collection中的常用方法
 * 	
 * 5. 规定:如果集合Collection中存储自定义类的对象,要求自定义类要重写equals().
 * 
 * 
 * 6. 集合:很常用。
 *    掌握:层次一:选择合适的集合类去实现数据的保存,调用其内部的相关方法。
 *    
 *        层次二:不同的集合类底层的数据结构为何?如何实现数据的操作的:增删改查等。
 */
public class CollectionTest {
	
	@Test
	public void test4(){
		Collection coll = new ArrayList();
		
		coll.add(new String("AA"));
		coll.add("MM");
		coll.add(new Person("Tom",12));
		coll.add(123);
		coll.add(456);
		//11.equals(Object obj):比较当前对象和obj是否相等。
		Collection coll1 = new ArrayList();
		
		coll1.add(new String("AA"));
		coll1.add("MM");
		coll1.add(new Person("Tom",12));
		coll1.add(123);
		coll1.add(456);
		boolean flag = coll.equals(coll1);
		System.out.println(flag);
		
		//12.hashCode():获取当前对象的哈希值
		System.out.println(coll.hashCode());
		
		//13.toArray():将集合转换为数组:Object[]
		Object[] arr = coll.toArray();
		for(int i = 0;i < arr.length;i++){
			System.out.println(arr[i]);
		}
		//14.toArray(T[] arr):略
		
		//15.iterator():涉及集合元素的遍历。 见 IteratorTest.java
	}
	
	@Test
	public void test3(){
		Collection coll = new ArrayList();
		
		coll.add(new String("AA"));
		coll.add("MM");
		coll.add(new Person("Tom",12));
		coll.add(123);
		coll.add(456);
		
		//8.remove(Object obj):从当前集合中移除obj元素。仍然需要调用到obj所在类的equals()
//		System.out.println(coll);
//		coll.remove(123);
//		coll.remove(new Person("Tom",12));
//		System.out.println(coll);
		
		//9.removeAll(Collection coll):差集:从当前集合中移除coll集合中的元素。
//		Collection coll1 = Arrays.asList(123,456);
//		coll.removeAll(coll1);
//		System.out.println(coll);
		
		//10.retainAll(Collection coll):交集:获取当前集合和coll集合的共有元素。
		Collection coll1 = Arrays.asList(123,456,678);
		coll.retainAll(coll1);
		System.out.println(coll);
		
	}
	
	@Test
	public void test2(){
		Collection coll = new ArrayList();
		
		coll.add(new String("AA"));
		coll.add("MM");
//		Person p = new Person("Tom", 12);
//		coll.add(p);
		coll.add(new Person("Tom",12));
		coll.add(123);
		coll.add(456);
		
		//6.contains(Object obj):判断当前集合中是否包含obj:调用了obj所在类的equals().
		
		boolean flag = coll.contains(new String("AA"));
		System.out.println(flag);//true
//		flag = coll.contains(p);
		flag = coll.contains(new Person("Tom",12));
		System.out.println(flag);//p:true--->new:false-->true
		
		
		//7.containsAll(Collection coll):当前集合中是否包含coll中的所有元素
		Collection list = Arrays.asList(new Integer[]{123,456});//从数组---->集合的转换
		flag = coll.containsAll(list);
		System.out.println(flag);//
	}
		
	@Test
	public void test1(){
		Collection coll = new ArrayList();
		
		//2.add(Object obj):将obj添加到当前的集合中
		coll.add("AA");
		coll.add("MM");
		coll.add(123);//自动装箱
		
		//1.size():返回集合中存储的数据的个数
		System.out.println(coll.size());
		
		//3.addAll(Collection coll):将coll集合中的所有元素添加到当前集合中
		Collection coll1 = new ArrayList();
		coll1.add(1);
		coll1.add(2);
		coll1.add(3);
		
		coll.addAll(coll1);
//		coll.add(coll1);
		
		System.out.println(coll);
		
		//5.clear():清空当前集合
		coll.clear();
		
		//4.isEmpty():判断当前集合是否为空
		System.out.println(coll.isEmpty());
		
	}
	
}

Collection接口继承树

Map接口继承树

9-2 Collection 接口API

Collection 接口
  • Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
  • JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。
  • 在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 JDK 5.0 增加了泛型以后,Java 集合可以记住容器中对象的数据类型
Collection 接口方法

9-3 Iterator迭代器接口

案例

/**
 * 集合的遍历:
 * 方式一:使用Iterator实现
 * 方式二:增强for循环(jdk 5.0 :foreach循环)
 * 
 */
public class IteratorTest {
	
	//笔试题:
	@Test
	public void test4(){
		String[] arr = new String[]{"MM","MM","MM","MM"};
		
//		for(int i = 0;i < arr.length;i++){
//			arr[i] = "GG";
//		}
		
		
		for(String s : arr){
			s = "GG";
		}
		
		/*
		 * int m = 10;
		 * int n = m;
		 * n = 20;
		 * sysout(m);
		 */
		
		for(int i = 0;i < arr.length;i++){
			System.out.println(arr[i]);
		}
	}
	
	@Test
	public void test3(){
		Collection coll = new ArrayList();
		
		coll.add(new String("AA"));
		coll.add("MM");
		coll.add(new Person("Tom",12));
		coll.add(123);
		coll.add(456);
		
		//for(集合元素的类型  局部变量 : 集合引用){}
		for(Object obj : coll){
			System.out.println(obj);
		}
		
		System.out.println("**************************");
		
		//增强for循环用来遍历数组
		int[] arr = new int[]{1,2,3,4,5,6,7};
		for(int a : arr){
			System.out.println(a);
		}
	}
	
	
	//错误的使用方式:
	@Test
	public void test2(){
		Collection coll = new ArrayList();
		
		coll.add(new String("AA"));
		coll.add("MM");
		coll.add(new Person("Tom",12));
		coll.add(123);
		coll.add(456);
		
		//错误方式一:
//		Iterator iterator = coll.iterator();
//		while(iterator.next() != null){
//			System.out.println(iterator.next());
//		} 
		//错误方式二:
//		while(coll.iterator().hasNext()){
//			System.out.println(coll.iterator().next());
//		}
		
	}
	
	@Test
	public void test1(){
		Collection coll = new ArrayList();
		
		coll.add(new String("AA"));
		coll.add("MM");
		coll.add(new Person("Tom",12));
		coll.add(123);
		coll.add(456);
		
		Iterator iterator = coll.iterator();//List list = Arrays.asList(T ... t);
		
		//方式一:
//		System.out.println(iterator.next());
//		System.out.println(iterator.next());
//		System.out.println(iterator.next());
//		System.out.println(iterator.next());
//		System.out.println(iterator.next());
		//执行报NoSuchElementException的异常
//		System.out.println(iterator.next());
		
		//方式二:
//		for(int i = 0;i < coll.size();i++){
//			System.out.println(iterator.next());
//		}
		
		//方式三:
		//hasNext():判断是否还有下一个元素
		while(iterator.hasNext()){
			//next():①指针下移 ②将下移以后集合位置上的元素返回
			System.out.println(iterator.next());
		}
	}
}

public class Person {
	private String name;
	private int age;
	public Person() {
		super();
	}
	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) {
		System.out.println("Person equals...");
		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;
	}	
}
使用 Iterator 接口遍历集合元素
  • Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
  • 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
  • Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。
Iterator接口的方法

使用 foreach 循环遍历集合元素

练习:判断输出结果为何?
public class TestFor {
      public static void main(String[] args){
             String[] str = new String[5];
             for(String myStr : str){
                    myStr = "xxxxx";
                    System.out.println(myStr);
              }
             for(int i = 0;i < str.length;i++){
                    System.out.println(str[i]);
             }
       }
}

9-4 Collection子接口之一:List 接口

List接口
  • Java中数组用来存储数据的局限性。
  • List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  • JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。

案例

/**
 * java.util.Collection:单列数据
 *   	|------List子接口:存储有序的、可重复的数据 ---->"动态"数组
 *   		|-----ArrayList:作为List的主要实现类;线程不安全的,效率高;底层使用数组实现
 *               (Collections中定义了synchronizedList(List list)将此ArrayList转化为线程安全的)
 *   		|-----LinkedList:对于频繁的插入、删除操作,我们建议使用此类,因为效率高;底层使用双向链表实现
 *   		|-----Vector:List的古老实现类;线程安全的,效率低;底层使用数组实现
 *   
 *   
 *   [面试题] ArrayList、LinkedList、Vector区别?
 *   		共同点:ArrayList、LinkedList、Vector都是List接口的实现类,存储的数据都是有序的、可重复的。
 *          区别:如上
 *          
 *          List list = new ArrayList();//jdk 7.0 : Object[] elementData = new Object[10];
 *          sysout(list.size());//0
 *          list.add(..);//elementData[0] = ..
 *          ...
 *          ...
 *          一旦要添加的元素超出了底层数组的长度,就需要扩容,默认扩容为原来的1.5倍,同时,需要将原有数组
 *       中的元素复制新的数组中。
 *          ...
 *          
 *       实际情况:需要存储80个数据到ArrayList中,建议:List list = new ArrayList(85);
 *   		
 * 
 * 
 * 说明:1.向List中添加自定义类的对象的话,要求此自定义类重写equals()方法!
 *      2.补充:数据结构解决两个问题:
 *             1.数据之间逻辑关系:一对一,一对多,多对多,...
 *             2.数据的存储结构:①顺序存储:一维数组  ②链式存储
 */
public class ListTest {
	/*
	 * 在Collection的基础上,新增的方法:
void add(int index, Object ele):在index位置插入ele元素
boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
Object get(int index):获取指定index位置的元素
int indexOf(Object obj):返回obj在集合中首次出现的位置.如果不存在,返回-1.
int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置.如果不存在,返回-1.
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index, Object ele):设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的左闭右开区间的子集合
	
	substring(int from ,int to) /  read(int from,int length)
	
	总结:List中的常用方法:
	增:add(Object obj)
	删:remove(Object obj) / remove(int index)
	改:set(int index, Object ele)
	查:get(int index)
	插:add(int index, Object ele)
	遍历:iterator();增强for;for
	长度:size()
	
	 */
	//遍历
	@Test
	public void test4(){
		List list = new ArrayList();
		list.add(123);
		list.add(456);
		list.add("AA");
		list.add(new Person("Tom",12));
		list.add(456);
		
		//遍历方式一:
		Iterator iterator = list.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
		System.out.println("*************");
		//遍历方式二:
		for(Object o : list){
			System.out.println(o);
		}
		System.out.println("*************");
		//遍历方式三:因为List提供索引
		for(int i = 0;i < list.size();i++){
			System.out.println(list.get(i));
		}
		
	}
	
	@Test
	public void test3(){
		List list = new ArrayList();
		list.add(123);
		list.add(456);
		list.add("AA");
		list.add(new Person("Tom",12));
		list.add(456);
		//修改:
		list.set(1, "BB");
		System.out.println(list);
		
		//获取子集合:
		List subList = list.subList(1, 3);
		System.out.println(subList);
		
	}
	@Test
	public void test2(){
		List list = new ArrayList();
		list.add(123);
		list.add(456);
		list.add("AA");
		list.add(new Person("Tom",12));
		list.add(456);
		
		int index = list.indexOf(456);
		System.out.println(index);
		
		int lastIndex = list.lastIndexOf(456);
		System.out.println(lastIndex);
		
		
		Object obj = list.remove(2);
		System.out.println(obj);
		System.out.println(list);
		System.out.println(list.get(2));
	}
	
	
	@Test
	public void test1(){
		List list = new ArrayList();
		list.add(123);
		list.add(456);
		list.add("AA");
		list.add(new Person("Tom",12));
		
		System.out.println(list);
		
		//插入:add(int index, Object ele)
		list.add(1, "BB");
		System.out.println(list);
		
		//插入:addAll(int index, Collection eles)
		List list1 = Arrays.asList(1,2,3);
		list.addAll(2, list1);
//		list.add(2,list1);
		System.out.println(list);
		
		//查询:get(int index)
		System.out.println(list.get(1));
		
	}
}
List实现类之一:ArrayList
  • ArrayList 是 List 接口的典型实现类、主要实现类

  • 本质上,ArrayList是对象引用的一个”变长”数组

  • ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector

  • Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合

【面试题】
public static void main(String[] args) {
	List<Integer> list = new ArrayList<Integer>();
	list.add(1);
	list.add(2);
	list.add(3);
	updateList(list);
	System.out.println(list);//[1,3]
}

private static void updateList(List<Integer> list) {
	//list.remove(new Integer(2));
	list.remove(2);
}
List实现类之二:LinkedList

案例

import java.util.Iterator;
import java.util.LinkedList;

public class LinkedListDemo {
	//LinkedList它内部封装的是双向链表数据结构
	//每个借点是一个Node对象,Node对象中封装的是你要添加的元素.
	//还有一个指向上一个Node对象的应用和指向下一个Node对象的引用
	/*
	 不同的容器有不同的数据结构,不同的数据结构操作起来性能是不一样的
	 连接数据结构,做插入、删除的效率比较高,但查询效率比较低(LinkedList)
	 
	  数组结构,它做查询的时候效率高,因为可以通过下标直接找到元素
	  但插入和删除效率比较低,因为要做位移操作.(ArrayList)
	 */
public static void main(String[] args) {
	//boolean         add(E e) 将指定的元素添加到此列表的尾部。 
	//void               add(int index, E element)  将指定的元素插入此列表中的指定位置。 
	// E               set(int index, E element)   用指定的元素替代此列表中指定位置上的元素。 
	// Iterator<E>  iterator() 返回以恰当顺序在此列表的元素上进行迭代的迭代器。 (此方法在其父类AbstractSequentialList<E>中)
	// E             removeFirst()  移除并返回此列表的第一个元素。 
	// E             pollFirst()  获取并移除此列表的第一个元素;如果此列表为空,则返回 null。 
	LinkedList<String> sList = new LinkedList<String>();
	//如果用父类的引用指向子类对象List->LinkedList  那么LinkedList自有的方法不能使用
	sList.add("zhansan");
	sList.add("lisi");
	sList.add("wangwu");
	sList.add("rose");
	sList.add("mary");
	sList.add("jack");
	sList.addFirst("aa");
	sList.addLast("bb");
	Iterator<String> it = sList.iterator();
		//Iterator迭代器对象的方法
		//boolean hasNext() 如果仍有元素可以迭代,则返回 true。 
		//E       next()    返回迭代的下一个元素。 
		//void    remove()    从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。 
		// E get(int index) 返回此列表中指定位置上的元素。 
	while(it.hasNext()){
		String name = it.next();
		System.out.print(name+"   ");
		//aa   zhansan   lisi   wangwu   rose   mary   jack   bb 
	}
	System.out.println();
	for(Iterator<String> it1 = sList.iterator();it1.hasNext();){
		String name1 = it1.next();
		System.out.print(name1+"   ");
		//aa   zhansan   lisi   wangwu   rose   mary   jack   bb 
	}
	System.out.println();
	for (String string : sList) {
		System.out.print(string+"   ");
		//aa   zhansan   lisi   wangwu   rose   mary   jack   bb 
	}
	System.out.println();
	System.out.println(sList.removeFirst());//aa
	System.out.println(sList.size());//7
	System.out.println(sList.pollFirst());//zhansan
	System.out.println(sList.size());//6
	sList.clear();
	System.out.println(sList.pollFirst());//null
	
}
}

LinkedList模拟堆栈

import java.util.Iterator;
import java.util.LinkedList;
//堆栈后进先出
public class LinkedListDemo1 {
public static void main(String[] args) {
	MyStack<String> mystack = new MyStack<String>();
	mystack.push("zhangsan");
	mystack.push("lisi");
	mystack.push("wangwu");
	mystack.push("zhaoliu");
	mystack.pop();
	mystack.pop();
	Iterator<String> it = mystack.iterator();
	while(it.hasNext()){
		System.out.print(it.next()+"  ");//lisi  zhangsan  
	}
}
}


class MyStack<T>{
	private LinkedList<T> data = null;
	public MyStack(){
		data=new LinkedList<T>();
	}
	//压栈的方法
	public void push(T obj){
		data.addFirst(obj);
	}
	//出栈的方法
	public T pop(){
		return data.removeFirst();
	}
	public Iterator<T> iterator(){
		return data.iterator();
	}
}

自己实现LinkedList

https://blog.csdn.net/qq_34436819/article/details/53850925

自建ArrayList及Iterator

public interface Iterator<T> {
public boolean hasNext();//判断是否有下一个元素
public T next();//获取下一个元素的内容
}

public interface List<T>{
public void add(T obj);//给具体的容器添加元素
public T get(int index);//获取指定位置上的元素
public int size();//获取容器中的元素个数
public Iterator<T> iterator();//获取迭代器
}

public class ArrayList implements List { private Object [] obj =null;//声明一个Object类型的数组 private int index;//数组的下标 private int size;//记录数组中元素的个数
	public ArrayList() {
	super();
	obj = new Object[10];
	index=0;
	size=0;
}

	@Override
	public void add(T obj) {
		this.obj[index++]=obj;//把数据存放到数组中
		size++;
	}

	@SuppressWarnings("unchecked")//压制警告
	@Override
	public T get(int index) {
		return (T) this.obj[index];
	}

	@Override
	public int size() {
		return size;
	}

	@Override
	public Iterator<T> iterator() {
		return new MyIterator<T>(this);
	}

	

}

public class MyIterator implements Iterator { private List list =null; private int index = 0;//访问到容器中元素的当前下标
	public MyIterator(List<T> list) {
	super();
	this.list = list;
}
//判断是否有下一个元素
	@Override
	public boolean hasNext() {
		return index<list.size();
	}
//取出下一个元素
	@Override
	public T next() {
		return list.get(index++);
	}

}

public class Test {
public static void main(String[] args) {
	List<String> nameList = new ArrayList<String>();
	nameList.add("zhangsan");
	nameList.add("lisi");
	nameList.add("wangwu");
	nameList.add("aa");
	nameList.add("bb");
	Iterator<String> it = nameList.iterator();
	while(it.hasNext()){
		System.out.println(it.next());
	}
	System.out.println("********");
	for (int i = 0; i < nameList.size(); i++) {
		System.out.println(nameList.get(i));
	}
}
}
  • 对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
  • 新增方法:
    • void addFirst(Object obj)
    • void addLast(Object obj)
    • Object getFirst()
    • Object getLast()
    • Object removeFirst()
    • Object removeLast()
List 实现类之三:Vector
  • Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。
  • 在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。
  • 新增方法:
    • void addElement(Object obj)
    • void insertElementAt(Object obj,int index)
    • void setElementAt(Object obj,int index)
    • void removeElement(Object obj)
    • void removeAllElements()

【面试题】

public static void main(String[] args) {
	List<Integer> list = new ArrayList<Integer>();
	list.add(1);
	list.add(2);
	list.add(3);
	updateList(list);
	System.out.println(list);
}

private static void updateList(List<Integer> list) {
	list.remove(new Integer(2));
}

答案:[1,3]

9-5 Collection子接口之二:Set 接口

Set 接口

/**
 * 
 * java.util.Collection:单列数据
 * 		|------List子接口:存储有序的、可重复的数据 ---->"动态"数组
 *   		
 *   	|------Set子接口:存储无序的、不可重复的数据 ----->高中讲的"集合"
 * 				|-----HashSet:是Set的主要实现类。底层实现:HashSet底层使用了HashMap.
 * 					|-----LinkedHashSet:是HashSet的子类,可以按照添加的顺序实现遍历。
 *                       (原因:在HashSet底层存储结构的基础上,额外提供了一对指针。能够记录此Node元素的
 *                       上一个和下一个元素。)--->对于频繁的遍历,效率高。
 * 								
 * 				|-----TreeSet:可以按照添加的元素的指定属性的大小实现遍历。底层实现:红黑树
 *
 */
public class SetTest {
	
	
	/**
	 * TreeSet的定制排序:
	 * 1.提供Comparator接口匿名实现类的对象
	 * 2.重写其中的compare(Object o1,Object o2),指明排序的规则。
	 * 3.将此实现类的对象作为参数传递到TreeSet的构造器中
	 * 4.向TreeSet的对象中添加compare()方法中判断的类的对象。
	 * 
	 * 总结:
	 * 元素是否能add成功,是否能remove,是否contains,...都依赖于compareTo()或compare().
	 * 与元素所在类的equals()/hashCode()无关!
	 * 
	 */
	@Test
	public void test4(){
		//提供Comparator接口匿名实现类的对象
		Comparator com = new Comparator(){
				
			@Override
			public int compare(Object o1, Object o2) {
				if(o1 instanceof Customer && o2 instanceof Customer){
					Customer c1 = (Customer)o1;
					Customer c2 = (Customer)o2;
					
					return c1.getAge() - c2.getAge();
				}
				
				return 0;
			}
			
		};
		
		
		Set set = new TreeSet(com);
		
		set.add(new Customer("Tom", 12));
		set.add(new Customer("Jerry", 2));
		set.add(new Customer("HanMeimei", 52));
		set.add(new Customer("Lilei", 44));
		set.add(new Customer("Yaoming", 44));
		
		set.remove(new Customer("Yaoming", 44));
		
		Iterator iterator = set.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
		
		
		
	}
	
	/**
	 * TreeSet的使用
	 * 1.向TreeSet中添加的元素必须是同一个类创建的对象。
	 * 
	 * 2.TreeSet排序的方式:① 自然排序(Comparable)  ②定制排序(Comparator)
	 * 3.自然排序:
	 * 		①要求添加的元素所在的类要实现Comparable接口
	 *      ②重写接口中的compareTo(Object obj)--->指明排序的规则
	 *         如果此方法返回值为0,则新要添加的元素添加不成功。
	 *      ③向TreeSet中添加此实现类的对象即可。
	 */
	@Test
	public void test3(){
		Set set = new TreeSet();
		
		//错误的!
//		set.add(new String("BB"));
//		set.add("AA");
//		set.add(123);
//		set.add(new Person("Tom", 12));
		
		
		//方式一:
//		set.add(new String("BB"));
//		set.add("AA");
//		set.add("OO");
//		set.add("KK");
//		set.add("JJ");
		
		//方式二:
//		set.add(45);
//		set.add(-45);
//		set.add(5);
//		set.add(475);
//		set.add(75);
//		set.add(-75);
		
		//方式三:
		set.add(new Person("Tom",35));
		set.add(new Person("Jerry",32));
		set.add(new Person("HanMeimei",32));
		set.add(new Person("Lilei",3));
		set.add(new Person("YaoMing",23));
		set.add(new Person("张学友",33));
		set.add(new Person("李嘉诚",33));
		
		Iterator iterator = set.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
	}
	
	
	@Test
	public void test2(){
		Set set = new LinkedHashSet();
		
		set.add(new String("BB"));
		set.add(new String("BB"));
		set.add("AA");
		set.add(123);
		set.add(123);
		set.add(new Person("Tom", 12));
		set.add(new Person("Tom", 12));
		
		Iterator iterator = set.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
		
	}
	
	
	/**
	 * Set作为Collection的子接口,没有定义额外的方法。
	 * 
	 * 
	 * Set:存储无序的、不可重复的数据
	 * 1.无序性:   != 随机性。 添加的元素,需要计算其哈希值,此哈希值决定了在底层的存储位置。从存储位置上看,是无序的。
	 * 
	 * 2.不可重复性:保证Set集合中的不同对象使用对象所属类的equals()判断的话,一定返回false.
	 * 
	 * 3.如何向Set中添加一个元素?哈希算法。
	 *  向Set中添加元素a,首先通过hashCode(),计算元素a的哈希值,此哈希值就决定了此元素在Set底层存储的位置。
	 *  如果此存储的位置上没有元素,则此元素a添加成功。如果此存储的位置上有元素b,则调用元素a所在类的equals()方法,
	 *  将元素b作为参数传递过去。如果返回值为true,则表示元素a和b相同,则元素a添加不成功。如果返回值为false,则
	 *  认为元素a和元素b不相同。此时元素a可以添加成功的。元素a与元素b使用链表存储。
	 *  (jdk 7.0 :a指向b;jdk8.0:b指向a)
	 * 
	 * 
	 * 4.向Set中添加的元素,要求其所在的类要重写两个方法:
	 *   equals() 和 hashCode().
	 * 5. 必须要求添加的元素所在的类中重写的equals() 和 hashCode() 保持一致性。
	 */
	@Test
	public void test1(){
		Set set = new HashSet();
		
		set.add(123);
		set.add(123);
		set.add(new String("BB"));
		set.add(new String("BB"));
		set.add("AA");
		set.add(new Person("Tom", 12));
		set.add(new Person("Tom", 12));
		
		Iterator iterator = set.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
		
	}
}

public class Person implements Comparable{
	private String name;
	private int age;
	public Person() {
		super();
	}
	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() { //return age + name.hashCode();
		//为什么使用31? 质数。   2 * 32 最高效的方式? 2 << 5 ; 7  17  31 
		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;
//		return false;
	}
	
	//此方法的重写,就决定了向TreeSet中添加数据的顺序。
	@Override
	public int compareTo(Object o) {
		
		if(o instanceof Person){
			Person p = (Person)o;
			int value = this.age - p.age;
			if(value != 0){
				return value;
			}else{
				return this.name.compareTo(p.name);
			}
		}
		
		return 0;

	}
}

public class Customer {
	private String name;
	private int age;
	public Customer(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 "Customer [name=" + name + ", age=" + age + "]";
	}
	
	
}
Set 接口
  • Set接口是Collection的子接口,set接口没有提供额外的方法
  • Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
  • Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法
Set实现类之一:HashSet

hashCode() 方法
  • 如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
  • 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。
  • 重写 hashCode() 方法的基本原则
    • 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值
    • 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等
    • 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值
Set实现类之二:LinkedHashSet
  • LinkedHashSet 是 HashSet 的子类
  • LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
  • LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
  • LinkedHashSet 不允许集合元素重复。
Set实现类之三:TreeSet
  • TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
    • Comparator comparator()
    • Object first()
    • Object last()
    • Object lower(Object e)
    • Object higher(Object e)
    • SortedSet subSet(fromElement, toElement)
    • SortedSet headSet(toElement)
    • SortedSet tailSet(fromElement)
  • reeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
排 序——自然排序


排 序——定制排序


【面试题】

HashSet set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002,"BB");

set.add(p1);
set.add(p2);
p1.name = "CC";
set.remove(p1);
System.out.println(set);
set.add(new Person(1001,"CC"));
System.out.println(set);
set.add(new Person(1001,"AA"));
System.out.println(set);

其中Person类中重写了hashCode()和equal()方法

9-6 Map接口

Map接口

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

import org.junit.Test;

/**
 * java.util.Map:
 * 
 * 		|------HashMap:Map的主要实现类;线程不安全的,效率高;可以存储null的key和value
 * 				(存储结构:jdk7.0 数组+链表; jdk8.0 数组+链表+红黑树)
 * 			|-----LinkedHashMap:HashMap的子类,可以按照添加的顺序遍历。对于频繁的遍历效率较高。
 * 				(在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序)
 * 		|------TreeMap:可以按照key的指定的属性进行排序。底层实现:红黑树
 * 		|------Hashtable:Map的古老实现类;线程安全的,效率低;不可以存储null的key和value
 * 			|-----Properties:Hashtable的子类,常常用来处理属性文件。其key和value都是String型。
 * 
 *  面试题:HashMap和Hashtable的对比。
 */
public class MapTest {
	
	@Test
	public void test1(){
		Map map = new HashMap();
		map = new Hashtable();
		map.put(null, 123);
	}
	
	
	/**
	 * Map:存储的是双列数据:key-value
	 * 1.所有的key构成的集合是Set:无序的、不可重复的
	 * 2.所有的value构成的集合是Collection:无序的、可以重复的
	 * 3.一个key-value构成一个Entry
	 * 4.所有的Entry构成的集合是Set:无序的、不可重复的
	 * 
	 * 
	 * HashSet的底层是使用HashMap进行存储的。
	 * HashMap的所有的key构成集合就是HashSet。
	 * 
	 * 
	 * 面试题:HashMap的底层实现原理?
	 * 	    HashMap map = new HashMap();//底层创建了长度为16的Entry数组
	 *      向HashMap中添加entry1(key,value),需要首先计算entry1中key的哈希值(根据key所在类的hashCode()计算
	 *      得到),此哈希值经过处理以后,得到在底层Entry[]数组中要存储的位置i.如果位置i上没有元素,则entry1直接添加成功。
	 *      如果位置i上已经存在entry2(或还有链表存在的entry3,entry4),则需要通过循环的方法,依次比较entry1中key和其他
	 *      的entry是否equals.如果返回值为true.则使用entry1的value去替换equals为true的entry的value.如果遍历一遍以后,
	 *      发现所有的equals返回都为false,则entry1仍可添加成功。entry1指向原有的entry元素。
	 *      
	 * 		默认情况下,如果添加元素的长度 >= DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR (默认值为12)
	 *      且新要添加的数组位置不为null的情况下,就进行扩容。默认扩容为原有长度的2倍。将原有的数据复制到新的数组中。
	 *      
	 *      
	 *  jdk 8.0 :
	 *  1.HashMap map = new HashMap();//默认情况下,先不创建长度为16的数组。
	 *  2.当首次调用map.put()时,再创建长度为16的数组
	 *  3.当数组指定索引位置的链表长度>8时,且map中的数组的长度> 64时,此索引位置上的所有entry使用红黑树进行存储。
	 *  
	 *  
	 *  LinkedHashMap:
	 *  HashSet:
	 *  LinkedHashSet:
	 *      
	 */
}
Map接口
  • Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
  • Map 中的 key 和 value 都可以是任何引用类型的数据
  • Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法。
  • 常用String类作为Map的“键”。
  • key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value

Map 常用方法

Map常用方法

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;

import org.junit.Test;

public class MapTest {
	
	//Map的常用类:
	
	//Hashtable的子类:Properties.
	//特点:key和value都是String类型
	//应用:常常用来处理属性文件
	@Test
	public void test5(){
		Properties pros = new Properties();
		
		try {
			FileInputStream fis = new FileInputStream("jdbc.properties");
			
			pros.load(fis);
			
			String name = pros.getProperty("name");
			String password = pros.getProperty("password");
			
			System.out.println("name = " + name + ",password = " + password);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/*
	 * 测试TreeMap
	 * 
	 * TreeMap可以按照key中指定的属性进行排序:自然排序 ; 定制排序
	 */
	@Test
	public void test4(){
		//自然排序
		Map map = new TreeMap();
		map.put("name5", "Tom5");
		map.put("name4", "Tom51");
		map.put("name7", "Tom53");
		map.put("name2", "Tom55");
		map.put("name9", "Tom57");
		
		System.out.println(map);
		
		
		//定制排序:
		Comparator com = new Comparator(){
			@Override
			public int compare(Object o1, Object o2) {
				if(o1 instanceof Customer && o2 instanceof Customer){
					Customer c1 = (Customer)o1;
					Customer c2 = (Customer)o2;
					
					return c1.getAge() - c2.getAge();
				}
				
				return 0;
			}
		};
		
		Map map1 =  new TreeMap(com);
		map1.put(new Customer("Tom", 21), 1004);
		map1.put(new Customer("Tom", 22), 1002);
		map1.put(new Customer("Tom", 6), 1001);
		map1.put(new Customer("Tom", 99), 1005);
		
		System.out.println(map1);
		
		
	}
	//测试LinkedHashMap
	@Test
	public void test3(){
		Map map = new HashMap();
		map = new LinkedHashMap();
		
		map.put("id", 1001);
		map.put("name", "Tom");
		map.put("salary", 5600.2);
		
		System.out.println(map);
	}
	
	
	//Map中的常用方法测试:
	/*
	 * 如何遍历Map
Set keySet()
Collection values()
Set entrySet()



	总结:
	增:put(Obejct key,Object value)
	删:remove(Object key)
	改:put(Obejct key,Object value)
	查:get(Object key)
	长度:size()
	遍历:keySet() / values() / entrySet()
	
	
	List (index--->数据)/ Set(很少用) / Map (key --- 数据)
	
	 */
	@Test
	public void test2(){
		Map map = new HashMap();
		
		map.put("id", 1001);
		map.put("name", "Tom");
		map.put("salary", 5600.2);
		
		//1.遍历所有的key:keySet()
		Set keySet = map.keySet();
		Iterator iterator = keySet.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
		System.out.println();
		
		//2.遍历所有的value:values();
		Collection values = map.values();
		for(Object o : values){
			System.out.println(o);
		}
		System.out.println();
		//3.遍历所有的key-value
		//方式一:
		Set keySet1 = map.keySet();
		for(Object key : keySet1){
			System.out.println(key + "---->" + map.get(key));
		}
		
		//方式二:
		Set entrySet = map.entrySet();
		for(Object o : entrySet){
			Map.Entry entry = (Map.Entry)o;
			System.out.println(entry.getKey() + "********" + entry.getValue());
		}
		
	}
	
	
	/*
Object put(Object key,Object value)
Object remove(Object key)
void putAll(Map t)
void clear()
Object get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
boolean equals(Object obj)

	 */
	@Test
	public void test1(){
		Map map = new HashMap();
		
		//添加:put(Object key,Object value)
		map.put("name", "Tom");
		map.put("id", 1001);
		map.put("salary", 5600.2);
		
		System.out.println(map);
		
		//修改:put(Object key,Object value)
		map.put("name", "Jerry");
		
		System.out.println(map);
		
		//删除:Object remove(Object key)
		Object value = map.remove("id");
		System.out.println(value);
		
		//长度:size()
		System.out.println(map.size());
		
		//清空数据:clear()
//		map.clear();//与map = null不同;
		
		//是否为空:isEmpty();
		System.out.println(map.isEmpty());
		
		//
		boolean flag = map.containsKey("salary");
		System.out.println(flag);
		flag = map.containsValue("Tom");
		System.out.println(flag);
		
		
		
	}
}

public class Customer {
	private String name;
	private int age;
	public Customer(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 "Customer [name=" + name + ", age=" + age + "]";
	}
	
	
}
  • 添加、删除操作: + Object put(Object key,Object value) + Object remove(Object key) + void putAll(Map t) + void clear()
  • 元视图操作的方法:
    • Set keySet()
    • Collection values()
    • Set entrySet()
  • 元素查询的操作:
    • Object get(Object key)
    • boolean containsKey(Object key)
    • boolean containsValue(Object value)
    • int size()
    • boolean isEmpty()
    • boolean equals(Object obj)
Map实现类之一:HashMap
  • Map接口的常用实现类:HashMap、TreeMap和Properties。
  • HashMap是 Map 接口使用频率最高的实现类。
  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
  • HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
  • HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。
HashMap的存储结构

JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。

Map实现类之二:LinkedHashMap
  • LinkedHashMap 是 HashMap 的子类
  • 与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致
Map实现类之三:TreeMap
  • TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
  • TreeMap 的 Key 的排序:
    • 自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
    • 定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
  • TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
  • 若使用自定义类作为TreeMap的key,所属类需要重写equals()和hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0。
Map实现类之四:Hashtable
  • Hashtable是个古老的 Map 实现类,线程安全。
  • 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
  • 与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
  • Hashtable判断两个key相等、两个value相等的标准,与hashMap一致。
Map实现类之五:Properties
  • Properties 类是 Hashtable 的子类,该对象用于处理属性文件
  • 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型
  • 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法
  • Properties pros = new Properties();
  • pros.load(new FileInputStream("jdbc.properties"));
  • String user = pros.getProperty("user");
  • System.out.println(user);

9-7 Collections工具类

Collections工具类

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Test;

/**
 * Collections:用来操作集合框架(Collection / Map)的工具类。   ---->Arrays数组工具类。
 * 
 * 面试题:Collection 和 Collections 区别?
 *
 */
public class CollectionsTest {
	/*
	 * 
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

	 */
	
	@Test
	public void test1(){
		List list = new ArrayList();
		list.add(34);
		list.add(134);
		list.add(-34);
		list.add(-34);
		list.add(334);
		list.add(56);
		list.add(77);
		System.out.println(list);
		
//		Collections.reverse(list);
//		
//		System.out.println("reverse:" + list);
//		
//		Collections.shuffle(list);
//		System.out.println("shuffle:" + list);
//		
//		Collections.sort(list);
//		System.out.println("sort:" + list);
		
//		Collections.swap(list, 0, 2);
//		System.out.println("swap:" + list);
		
//		int frequency = Collections.frequency(list, -34);
//		System.out.println(frequency);
		
		/*
		 * copy(List dest,List src):将src中的内容复制到dest中
		 */
		//错误的:
//		List dest = new ArrayList();
//		Collections.copy(dest, list);
//		System.out.println(dest);
		
		//正确的:
		List dest = Arrays.asList(new Object[list.size()]);
		Collections.copy(dest, list);
		System.out.println(dest);
		
		//list:线程不安全的。
		List newList = Collections.synchronizedList(list);
		//newList:线程安全的。
	}
}
操作集合的工具类:Collections

操作数组的工具类:Arrays

  • Collections 是一个操作 Set、List 和 Map 等集合的工具类
  • Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
  • 排序操作:(均为static方法)
    • reverse(List):反转 List 中元素的顺序
    • shuffle(List):对 List 集合元素进行随机排序
    • sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
    • sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
    • swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

查找、替换

  • Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
  • Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
  • Object min(Collection)
  • Object min(Collection,Comparator)
  • int frequency(Collection,Object):返回指定集合中指定元素的出现次数
  • void copy(List dest,List src):将src中的内容复制到dest中
  • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
同步控制
  • ollections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题

补充:Enumeration
  • Enumeration 接口是 Iterator 迭代器的 “古老版本”

Enumeration stringEnum = new StringTokenizer("a-b*c-d-e-g", "-");
	while(stringEnum.hasMoreElements()){
		Object obj = stringEnum.nextElement();
		System.out.println(obj); 
	}
练 习

1.请用随机数输入10个整数保存到List中,并按倒序、从大到小的顺序显示出来

2.请把学生名与考试分数录入到集合中,并按分数显示前三名成绩学员的名字。

3.一个文件中有很多人员信息如:
张 三
李 四
王 五
李 按时若多撒多
输出姓氏及次数


import org.junit.Test;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;

public class CollectionTest {

    @Test
    public void test1() {
        //[0,1)
        //double random = Math.random();
        //System.out.println(random);
        List<Integer> list = new ArrayList<>();
        Random r = new Random();
        for (int i = 0; i < 10; i++) {
            //如果这个值要取[1,10)
            Integer value = (int) (r.nextDouble() * 10 + 1);
            list.add(value);
        }
//        倒序方法一
//        for (int i = 0; i < list.size(); i++) {
////            for (int j = 0; j < list.size()-1; j++) {
////                if(list.get(i)>list.get(j)){
////                    Integer temp = list.get(j);
////                    list.set(j,list.get(i)) ;
////                    list.set(i,temp) ;
////                }
////            }
////        }
////        System.out.println(list);
//        倒序方法二
//        System.out.println(list);
//        Collections.sort(list);
//        System.out.println(list);
//        Collections.reverse(list);
//        System.out.println(list);

//        倒序方法三
        System.out.println(list);
//        list.sort(new Comparator<Integer>() {
//            @Override
//            public int compare(Integer o1, Integer o2) {
//                return o2-o1;
//            }
//        });

        list.sort((o1, o2) -> {
            return o2 - o1;
        });
        System.out.println(list);
    }


    @Test
    public void test2() {
        Map<Student, Student> map = new TreeMap<>();
        String name = "松岛枫把老师把你的空间辣酸奶的经费困难辣椒";

        final DecimalFormat format = new DecimalFormat("#.##");
        int count = 0;
        i:
        {
            for (int i = 0; i < 20; i++) {
                int nameLenth = (int) (Math.random() * 3 + 2);
                String aaFianlName = "";
                if (count == 10) {
                    break i;
                }
                for (int i1 = 0; i1 < nameLenth; i1++) {
                    char aaName = name.charAt((int) (Math.random() * name.length()));
                    aaFianlName += aaName;
                }
                Random random = new Random();
                Double v = random.nextDouble() * 101;
                String format1 = format.format(v);
                double finalSource = Double.parseDouble(format1);
                if (!map.containsKey(new Student(aaFianlName, finalSource))) {
                    map.put(new Student(aaFianlName, finalSource), new Student(aaFianlName, finalSource));
                    count++;
                }
            }
        }
        System.out.println(map);
        Set<Map.Entry<Student, Student>> entries = map.entrySet();
        Iterator<Map.Entry<Student, Student>> iterator = entries.iterator();
        for (int i = 1; i <= 10; i++) {
            Map.Entry<Student, Student> next = iterator.next();
            next.getKey();
            next.getValue();
            System.out.println("第" + i + "名:" + next.getKey() + ",成绩: " + next.getValue());
        }
    }


    @Test
    public void test3() {
        List<String> ls = new ArrayList<>();
        try (FileInputStream fi = new FileInputStream("D:\\day22\\src\\comchengzi\\day22\\exer\\student")) {
            String l;
            InputStreamReader reader = new InputStreamReader(fi, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(reader);
            while ((l = bufferedReader.readLine()) != null) {
                ls.add(l);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(ls);

        Map<String, Integer> map = new HashMap<>();
        for (int i = 0; i < ls.size(); i++) {
            String[] split = ls.get(i).split(" ");
            if (map.containsKey(split[0])) {
                Integer integer = map.get(split[0]);
                map.put(split[0], integer + 1);
            } else {
                map.put(split[0], 0);
            }
        }
        System.out.println(map);

    }
}

import java.util.Objects;

public class Student implements Comparable<Student>{
    String name;
    Double Source;

    public Student(String name, Double source) {
        this.name = name;
        Source = source;
    }

    @Override
    public int compareTo(Student o) {
        return (int)(o.Source-this.Source);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", Source=" + Source +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) &&
                Objects.equals(Source, student.Source);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, Source);
    }
}

student.txt
张 三
李 四
王 五
李 按时若多撒多

集合总结一(ArrayList的实现原理)

集合总结二(LinkedList的实现原理)

集合总结三(HashMap的实现原理)

集合总结四(LinkedHashMap的实现原理)

集合总结五(Hashtable的实现原理)

posted on 2018-10-04 16:24  咘雷扎克  阅读(283)  评论(0编辑  收藏  举报

导航