黑马程序员-------集合

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1. Collection

类层次结构:

   Collection(接口)

         |--List(接口):1.有序的;2.可以存储重复值;

             |--ArrayList(类):数组实现;

         |--Set(接口):1.无序的;2.不能存储重复值;

1.1 Collection中的基本方法

/*
 * Collection中的基本方法:
 * 
 * 注意:如果大家在方法的形参或返回值类型中看到E字母,可以把它当做:Object
 * boolean add(Object e):将参数e添加到集合
 * boolean remove(Object o):将参数o从集合中移除
 * void clear():清空集合
 * boolean contains(Object o):基于equals()进行判断;
 * boolean isEmpty():判断集合是否为空
 * int size():集合中元素的数量;
 * 
 * 
 * 学习:Collection(List和Set的顶层接口)
 * 使用:子类:ArrayList

 */
public class Demo {
	public static void main(String[] args) {
		//1.定义集合对象
		Collection col = new ArrayList();//多态:可存储重复元素
		Collection col2 = new HashSet();//不能存储重复元素;
		
		//2.向仓库中添加元素
		System.out.println(col.add("孙悟空"));
		System.out.println(col.add("猪八戒"));
		System.out.println(col.add("沙师弟"));
		System.out.println(col.add("唐僧"));
		System.out.println(col.add("唐僧"));
		
		System.out.println("---------------------------");
		System.out.println(col2.add("孙悟空"));
		System.out.println(col2.add("猪八戒"));
		System.out.println(col2.add("孙悟空"));
		
		System.out.println("集合元素:" + col);
		//3.移除元素
		System.out.println("删除元素:唐僧: " + col.remove("唐僧"));
		System.out.println("删除元素:白骨精:" + col.remove("白骨精"));
		System.out.println("集合元素:" + col);
		
		//4.void clear()
	//	col.clear();
	//	System.out.println("清空集合后:" + col);
		
		//5.boolean contains(Object o)
		System.out.println("是否包含:白骨精:" + col.contains("白骨精"));
		System.out.println("是否包含:孙悟空:" + col.contains("孙悟空"));
		
		//6.boolean isEmpty()
	//	col.clear();
		System.out.println("集合是否为空:" + col.isEmpty());
		
		//7.int size():
		System.out.println("集合中元素的数量:" + col.size());
		
		//存储Student对象,使用数据,一旦定义长度,之后就不能改变;
		//所以,如果我们使用"集合"存储,我们就不用关心长度的问题;
		
	}
}

1.2 Collection中的批量操作元素的方法

/*
 * Collection中批量操作元素的方法:
 * 
 * boolean addAll(Collection c):将参数集合,一次性全部添加到当前集合
 * boolean removeAll(Collection c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作
 * boolean containsAll(Collection c):如果此 collection 包含指定 collection 中的所有元素,则返回 true
 * boolean retainAll(Collection c):移除此 collection 中未包含在指定 collection 中的所有元素。 

 */
public class Demo {
	public static void main(String[] args) {
		Collection c1 = new ArrayList();
		c1.add("孙悟空");
		c1.add("猪八戒");
		c1.add("唐三藏");
		
		Collection c2 = new ArrayList();
		c2.add("白骨精");
		c2.add("蜘蛛精");
		c2.add("狐狸精");
		
		//将集合c2中的所有元素,一次性全部添加到c1中
		/*c1.addAll(c2);
		System.out.println("c1.size : " + c1.size());//6
		System.out.println("c2.size : " + c2.size());//3
		System.out.println("c1 : " + c1);
		System.out.println("c2 : " + c2);
		*/
		
		/*c1.removeAll(c2);
		System.out.println("c1 : " + c1);
		System.out.println("c2 : " + c2);*/
		
	//	System.out.println(c1.containsAll(c2));
		
		System.out.println(c1.retainAll(c2));
		System.out.println("c1 : " + c1);
		System.out.println("c2 : " + c2);
		
		
	}
}

1.3 Collection中遍历

/*
 * 对于Collection类型的集合,有两种基本的遍历方法:
 * 
 * 1.Object[] toArray()方法:
 * 2.迭代器:Iterator iterator();
 * 
 * 		Iterator(接口):
 * 			boolean hasNext():  如果仍有元素可以迭代,则返回 true。 
 * 			Object next() :返回迭代的下一个元素。 

 */
public class Demo {
	public static void main(String[] args) {
		Collection c1 = new ArrayList();
		c1.add("孙悟空");
		c1.add("猪八戒");
		c1.add("唐三藏");
		
		//遍历方式一:
		Object[] objArray = c1.toArray();
		for(int i = 0;i < objArray.length ; i++){
			System.out.println(objArray[i]);
		}
		System.out.println("---------------------------");
		//遍历方式二:迭代器
		Iterator it = c1.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
		
	}
}

1.4 迭代器源码解析

interface Iterator{
	boolean hasNext();
	Object next();
	void remove();
}
interface Collection{
	Iterator iterator();
}
class ArrayList implements Collection{
	 public Iterator iterator() {
	        return new Itr();
	 }
	 private class Itr implements Iterator{
		public boolean hasNext() {
			return false;
		}
		public Object next() {
			return null;
		}
		public void remove() {
		}
		 
	 }
}

2.List

2.1 List方法

/*
 * Collection(接口):
 * 		|--List(接口):1.可以存储重复的;2.有序的(取出时的顺序同存入时)
 * 			特有方法:
 * 				void add(int index,E element):将element添加到index位置;原index位置上元素依次后移;
 * 				E remove(int index):移除index位置上的元素
 * 				E get(int index):获取index位置上的元素
 * 				E set(int index,E element):将element替换原index位置上的元素;
 * 
 * 				ListIterator listIterator():获取List的迭代器。ListIterator是Iterator的子接口;
 * 				跟Iterator的不同:
 * 				1.Iterator:单项的迭代器。只能向下遍历;
 * 				2.ListIterator:双向的迭代器,可以向上遍历;注意:在向上遍历前,一定要先向下遍历;
 * 				

 * 		|--Set(接口):1.不能存储重复元素;2.无序的;
 */
public class Demo {
	public static void main(String[] args) {
		//1.实例化一个集合
		List list = new ArrayList();
		list.add("张三");
		list.add("李四");
		list.add("王五");
		Iterator it = list.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
		
		//在"李四"之前,插入一个"赵七"
		list.add(1,"赵七");
		System.out.println("list :" + list);
		
		//移除"赵七"
		list.remove(1);
		System.out.println("移除赵七后:" + list);
		
		//获取王五
		System.out.println("获取王五:" + list.get(2));
		
		//将王五替换为赵七
		list.set(2, "赵七");
		System.out.println("将王五替换为赵七后:" + list);
		
		//结合Collection的size()和List的get()方法,可以遍历List类型的集合:
		for(int i = 0; i < list.size() ; i++){
			System.out.println(list.get(i));
		}
		System.out.println("-----------------------");
		//获取一个ListIterator
		ListIterator listIt  = list.listIterator();
		System.out.println("先向下遍历:");
		while(listIt.hasNext()){
			System.out.println(listIt.next());
		}
		System.out.println("向上遍历:");
		while(listIt.hasPrevious()){
			System.out.println(listIt.previous());
		}
		
		System.out.println("=====================");
		
		
	}
}

2.2 并发修改异常

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

/*
 * 并发修改异常:
 * 
 * 1.Iterator:remove()方法不会触发并发修改异常;
 * 2.ListIterator:remove()方法不会触发并发修改异常;
 *                set()方法不会触发并发修改异常;
 *                add()方法不会触发并发修改异常;
 * 3.当使用迭代器遍历元素时,通过List的对象去修改元素内容时,会引发并发修改异常:ConcurrentModificationException
 *   解决:
 *   使用迭代器遍历,如果要修改集合,就要通过迭代器去修改。不要通过List对象修改;
 */
public class Demo {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("张三");
		list.add("李四");
		list.add("王五");
		
		ListIterator listIt = list.listIterator();
		while(listIt.hasNext()){
			String str = (String)listIt.next();
			System.out.println(str);
			if(str.equals("李四")){
			//	listIt.remove();//OK的
			//	listIt.set("赵七");//OK的
			//	listIt.add("赵七");//OK的
				list.add("赵七");//并发修改异常:通过List对象去修改的;
			}
			
		}
		System.out.println("----------------------");
		Iterator it = list.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
		
		
	}
}

2.3 ArrayList

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

import cn.itcast.domain.Student;

public class ArrayListTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		List list = new ArrayList();
//		list.add("abc1");
//		list.add("abc2");
//		list.add("abc1");
//		list.add("abc2");
//		list.add("abc1");
//		list.add("abc2");
		
		list.add(new Student("lisi1",21));
		list.add(new Student("lisi2",22));
		list.add(new Student("lisi1",21));
		list.add(new Student("lisi2",22));
		list.add(new Student("lisi1",21));
		
		getSingleElement(list);//去除重复元素。
		
		System.out.println(list);

	}
	
	/*
	 * 案例:去除List集合中的重复元素。
	 * 
	 * 思路:
	 * 1,先创建一个临时容器。用于存储唯一性的元素。
	 * 2,遍历原容器,将遍历到的元素到临时容器中去判断,是否存在。
	 * 3,如果存在,不存储到临时容器,如果不存在,存储到临时容器中。
	 * 4,遍历结束后,临时容器中存储的就是唯一性的元素。
	 * 5,如果需要将这些唯一性的元素保留到原容器中,只要将原容器清空,将临时容器中的元素添加到原容器中即可。
	 * 
	 */
	public static void getSingleElement(List list){
		
		//1,创建一个临时容器。
		List temp = new ArrayList();
		
		//2,遍历原容器。
		for (Iterator it = list.iterator(); it.hasNext();) {
			Object obj = it.next();
			
			//对遍历到的每一个元素都到临时容器中去判断是否包含。
			if(!temp.contains(obj)){//如果不存在,
				temp.add(obj);//添加到临时容器。
			}
		}
		//唯一性的元素已经被记录到临时容器中。
		//清空原容器中的元素。
		list.clear();
		
		//把临时容器中的元素添加到原容器中。
		list.addAll(temp);
		
	}

}

2.4 LinkedList

import java.util.LinkedList;

public class LinkedListDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		/*
		 * LinkedList做个了解。
		 * 特有:围绕头和尾展开定义的。First Last。
		 * addFirst();
		 * addLast();
		 * 
		 * getFirst();:获取头部元素。
		 * getLast();
		 * 
		 * removeFirst();获取头部元素,并删除头部元素。
		 * removeLast();
		 */
		
		LinkedList link = new LinkedList();
		
		link.addFirst("abc1");
		link.addFirst("abc2");
		link.addFirst("abc3");
		
//		System.out.println(link.getFirst());
//		System.out.println(link.getFirst());
		
//		System.out.println(link.removeFirst());
//		System.out.println(link.removeFirst());
//		System.out.println(link.removeFirst());
//		System.out.println(link.removeFirst());
		
		while(!link.isEmpty()){
			
			System.out.println(link.removeLast());
		}
		
		
	}

}

2.5 LinkedList例子

import java.util.LinkedList;

public class LinkedListTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		/*
		 * 面试题:用LinkedList模拟一个堆栈或者队列数据结构。
		 * 创建一个堆栈或者队列数据结构对象,该对象中使用LinkedList来完成的。
		 * 
		 * 自定义堆栈结构。作业。
		 */
		//创建一个队列对象。
		Queue queue = new Queue();
		//往队列中添加元素。
		queue.myAdd("itcast1");
		queue.myAdd("itcast2");
		queue.myAdd("itcast3");
		queue.myAdd("itcast4");
		
		while(!queue.isNull()){
			System.out.println(queue.myGet());
		}
	}
}
/**
 * 定义一个队列数据结构。Queue
 */
class Queue{
	//封装了一个链表数据结构。
	private LinkedList link;
	/*
	 * 队列初始化时,对链表对象初始化。
	 */
	Queue(){
		link = new LinkedList();
	}
	
	/**
	 * 队列的添加元素功能。
	 */
	public void myAdd(Object obj){
		//内部使用的就是链表的方法。
		link.addFirst(obj);
	}
	
	/**
	 * 队列的获取方法。
	 */
	public Object myGet(){
		return link.removeLast();
	}
	
	/**
	 * 判断队列中元素是否空,没有元素就为true。
	 */
	public boolean isNull(){
		return link.isEmpty();
	}
}

3.Set

3.1 set方法

Set:不包含重复元素的集合,不保证顺序。而且方法和Collection一致。Set集合取出元素的方式只有一种:迭代器。

                            |--HashSet:哈希表结构,不同步,保证元素唯一性的方式依赖于:hashCode(),equals()方法。查询速度快。

                            |--TreeSet:可以对Set集合中的元素进行排序。使用的是二叉树结构。如何保证元素唯一性的呢?

         使用的对象比较方法的结果是否为0,是0,视为相同元素不存。

         元素的排序比较有两种方式:

1,元素自身具备自然排序,其实就是实现了Comparable接口重写了compareTo方法。

                   如果元素自身不具备自然排序,或者具备的自然排序不是所需要的,这时只能用第二种方式。

2,比较器排序,其实就是在创建TreeSet集合时,在构造函数中指定具体的比较方式。

                   需要定义一个类实现Comparator接口,重写compare方法。

                   到此为止:再往集合中存储对象时,通常该对象都需要覆盖hashCode,equals,

         同时实现Comparale接口,建立对象的自然排序。通常还有一个方法也会复写toString();

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

import cn.itcast.domain.Student;

public class SetDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Set set = new HashSet();
		
		/*
//		去除了字符串中的重复元素。
		set.add("nba");
		set.add("java");
		set.add("haha");
		set.add("itcast");
		set.add("haha");
		set.add("java");
		set.add("java");
		set.add("java");
		set.add("itcast");*/
		
		/*
		 * 
		 * 为什么学生对象没有保证唯一性呢?
		 * 通过对哈希表的分析。
		 * 存储元素时,先调用了元素对象的hashCode()方法,而每个学生对象都是新建立的对象,
		 * 所以hashCode值都不相同,也就不需要判断equals了。
		 * 想要按照需求同姓名同年龄来保证学生对象的唯一性咋办?
		 * 不能使用Object中hashCode方法,需要重新定义hashCode的算法内容。
		 * 简单说:重写hashCode方法。
		 */
		set.add(new Student("lisi1",21));
		set.add(new Student("lisi2",22));
		set.add(new Student("lisi1",21));
		set.add(new Student("lisi2",22));
		set.add(new Student("lisi1",21));
		
		"abc1".hashCode();
		
		for (Iterator it = set.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}

	}

}

3.2 HashSet

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

import cn.itcast.api.d.comparator.ComparatorByLength;

public class HashSetTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		Set set = new HashSet();

		set.add("abcde");
		set.add("haha");
		set.add("z");
		set.add("java");
		
//		Object max = Collections.max(set);
//		System.out.println("max="+max);

		Object obj1 = getMax(set);
		System.out.println(obj1);
//		Object obj2 = getMax(set,new ComparatorByLength());
//		System.out.println(obj2);

	}

	/**
	 * 获取Set集合的最大值,通过自然排序。
	 * @param set
	 * @return
	 */
	public static Object getMax(Set set) {

		/*
		 * 最值思路: 1,需要比较,并记录每次比较后较大的值。不断的重复这个动作(循环)
		 */

		// 1,定义变量,记录较大的值,初始化为元素中的任意一个。
		// 取出set集合中一个元素,通过迭代器。
		// 先获取迭代器。
		Iterator it = set.iterator();
		// 获取其中一个元素。
		Object max = it.next();

		// 2,遍历集合,获取集合的每一个元素,
		while (it.hasNext()) {

			Object o = it.next();
			
			Comparable temp = (Comparable) o;

			// 3,在遍历中,和变量中记录的元素进行比较。让变量记录住比较后较大值。
			if (temp.compareTo(max) > 0) {
				max = temp;
			}
		}

		// 4,返回最大值。
		return max;
	}

	/**
	 * 获取Set集合最大值,通过给定的比较器。
	 * @param set
	 * @param comp
	 * @return
	 */
	public static Object getMax(Set set, Comparator comp) {

		if (comp == null) {
			throw new NullPointerException();
		}
		/*
		 * 最值思路: 1,需要比较,并记录每次比较后较大的值。不断的重复这个动作(循环)
		 */

		// 1,定义变量,记录较大的值,初始化为元素中的任意一个。
		// 取出set集合中一个元素,通过迭代器。
		// 先获取迭代器。
		Iterator it = set.iterator();
		// 获取其中一个元素。
		Object max = it.next();

		// 2,遍历集合,获取集合的每一个元素,
		while (it.hasNext()) {
			Object o = it.next();
			// 3,在遍历中,和变量中记录的元素进行比较。让变量记录住比较后较大值。
			if (comp.compare(o, max) > 0) {
				max = o;
			}
		}

		// 4,返回最大值。
		return max;
	}

}

3.3 LinkedHashSet

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		/*
		 * 提高唯一性元素的查询效率,还想有序,可使用HashSet的子类LinkedHashSet.
		 */
		Set set = new LinkedHashSet();
		
		set.add("abcd");
		set.add("hahahah");
		set.add("java");
		set.add("itcast");
		
		for (Iterator it = set.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}

	}

}

3.4 TreeSet

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import cn.itcast.domain.Student;

public class TreeSetDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
	
		//演示TreeSet,
		Set set = new TreeSet();
		/*
		set.add("nba");
		set.add("abc");
		set.add("java");
		set.add("aaa");
		*/
		/*
		 * TreeSet的add方法内部最终实现:
		 * 需要将元素转成Comparable类型,为什么?因为这个类型具备排序的能力。
		 * 这个类型中有一个专门为排序提供了一个compareTo方法。
		 * 如果要让学生具备比较排序的功能,需要让学生扩展功能,实现Comparable接口。
		 */
		set.add(new Student("lisi6",21));
		set.add(new Student("lisi8",22));
		set.add(new Student("lisi5",25));
		set.add(new Student("lisi3",23));
		set.add(new Student("lisi7",20));
		
		
		
		for (Iterator it = set.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}
	}
}

3.5 TreeSet集合对象时明确比较器

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import cn.itcast.api.d.comparator.ComparatorByName;
import cn.itcast.domain.Student;

public class TreeSetDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//在创建TreeSet集合对象时明确比较器。
		Set set = new TreeSet(new ComparatorByName());
		/*
		 * 想要按照学生的姓名排序,说明学生中的自然排序不是所需要的。
		 * 这时只能使用比较器。ComparatorByName。
		 */
		set.add(new Student("lisi6",21));
		set.add(new Student("lisi8",22));
		set.add(new Student("lisi5",25));
		set.add(new Student("lisi3",23));
		set.add(new Student("lisi7",20));
		
		for (Iterator it = set.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}

	}

}


import java.util.Comparator;
import java.util.TreeMap;

import cn.itcast.domain.Student;

public class ComparatorByName extends Object implements Comparator {

	@Override
	public int compare(Object o1, Object o2) {
		//1,因为要比较的是学生对象的姓名。所以向下转型成Student对象。
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		
		//先比较姓名。
		int temp = s1.getName().compareTo(s2.getName());
		//如果姓名相同,再比较年龄。
		return temp==0? s1.getAge()-s2.getAge():temp;
	}

}

4.List和Set

 

集合分体系。List  Set

         子类对象的后缀名是所属体系,前缀名是数据结构名称。

         List:新出的子类都是以List结尾的,通常都是非同步的。

                   |--ArrayList:看到array,就知道数组,查询速度快。

                   |--LinkedList:看到link,就知道链表,增删速度快。

                  

         Set:

                   |--HashSet:看到hash,就知道哈希表,查询速度更快,并想到元素唯一,通过hashCode(),equals方法保证唯一性。

                   |--TreeSet:看到tree,就知道二叉树,可以排序,排序想到Comparable-compareToComparator--compare方法。

5.泛型

5.1泛型的由来和使用

 

1,因为集合可以存储的对象类型是任意的,在取出进行向下转型时,容易发生ClassCastException。

         所以JDK1.5以后就有了解决这个问题的技术:泛型。

2,泛型的原理:其实就是在操作的元素类型不确定时,通过传递参数的形式来明确类型。

3,泛型的体现就是 <参数类型变量>用于接收具体的实际元素类型。

4,泛型技术在集合框架中应用非常广泛,只要记住:在使用类或者接口时,如果接口上有明确<>泛型。在使用时,就传递所需的数据类型即可。不传递会出现警告类型不安全提示。

5,了解:泛型技术是用在编译器部分的技术,一旦类型检查正确,

                   生成的class文件中就没有泛型标记了:这是的泛型的擦除。

6,泛型的好处:

          6.1 将运行时期的ClassCastException异常转移到编译时期通过编译失败体现。

          6.2 避免了强制转换的麻烦。

7,其实泛型的使用就是往定义了泛型的类或者接口的<>中传递类型参数。

 

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

public class GenericDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		/*
		 * 为了让集合使用更安全,
		 * 问题:什么类型的元素都可以存储。导致取出时,如果出现强转就会引发运行时 ClassCastException。
		 * 能不能在创建集合时,就明确容器中的元素的类型,如同数组一样。
		 * 目的是为了更安全。
		 * JDK1.5以后,出现了解决方案,使用容器时,必须明确容器中元素的类型。
		 * 这种机制:称之为 :泛型。
		 * 体现 <数据类型>,不是很难理解,<>也是括号,往括号里面写东西其实就是在传递参数。
		 * 泛型:
		 * 1,安全机制。
		 * 2,将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
		 * 3,泛型技术,是给编译器使用的技术。
		 * 4,避免了强转的麻烦。
		 */
		//int[] arr = new int[];
		//创建集合时,直接在集合上明确要存储的元素的类型。
		List list = new ArrayList();
		
		list.add("abc");
		list.add("zzzz");
//		list.add(6);//只要不是指定的类型对象,编译器检查会 报错。这样将运行时的问题转移到编译时期。
		
		for (Iterator it = list.iterator(); it.hasNext();) {
//			Object object = (Object) it.next();
//			System.out.println(object.toString());
			//想要打印字符串的长度。
			String str = it.next();
			System.out.println(str.length());
			
		}
	}

}

5.2泛型的通配符

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import cn.itcast.domain.Person;
import cn.itcast.domain.Student;
import cn.itcast.domain.Worker;

public class GenericDemo6 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Set list = new HashSet();
		
		list.add(new Student("lisi1",21));
		list.add(new Student("lisi2",22));
		list.add(new Student("lisi3",23));
		
		printList(list);
		
		List list2 = new ArrayList();
		
		list2.add(new Worker("lisi11",21));
		list2.add(new Worker("lisi22",22));
		list2.add(new Worker("lisi33",23));
		
		printList(list2);

		
	}

	/*
	 *  打印集合中的元素。
	 *  当使用泛型类或者接口时,传递的具体的类型不确定,可以通过通配符(?)表示。
	 *  如果想要对被打印的集合中的元素类型进行限制,只在指定的一些类型,进行打印。
	 *  使用泛型的限定。
	 *  
	 *  只需要打印学生和工人的集合。找到学生和工人的共性类型Person。
	 *  ? extends Person : 接收Person类型或者Person的子类型。
	 *  
	 *  总结:
	 *  ? super E:接收E类型或者E的父类型。下限。
	 *  ? extends E:接收E类型或者E的子类型。上限。
	 */
	private static void printList(Collection list2) {
		for (Iterator it = list2.iterator(); it.hasNext();) {
			
			Person p = it.next();
			System.out.println(p.getName());
		}
	}
	

}

6. Collections工具类

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import cn.itcast.api.c.comparator.ComparatorByLength;

public class CollectionsDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		/*
		 * Collections: 集合框架中的用于操作集合对象 工具类。
		 * 都是静态的工具方法。
		 * 1,获取Collection最值。
		 * 2,对List集合排序,也可以二分查找。
		 * 3,对排序逆序。
		 * 4,可以将非同步的集合转成同步的集合。
		 * Xxx synchronizedXxx(Xxx)  List synchronizedList(List) 
		 */
		
		
		System.out.println("---------获取最值---------------");
		Collection c = new ArrayList();
		c.add("haha");
		c.add("zz");
		c.add("xixii");
		c.add("abc");
		String max = Collections.max(c,new ComparatorByLength());
		
		System.out.println("max="+max);
		System.out.println("-----------排序-------------");
		List list  = new ArrayList();
		list.add("hahaha");
		list.add("abc");
		list.add("xiix");
		list.add("z");
		list.add("java");
		Collections.sort(list,Collections.reverseOrder());
		System.out.println(list);
		
		
		System.out.println("------------------------");
		System.out.println("------------------------");
		
		
		
	}

}

7  Arrays工具类

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

public class ArraysDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		/*
		 * Arrays:用于操作数组的工具类。
		 * 类中定义的都是静态工具方法
		 * 1,对数组排序。
		 * 2,二分查找。
		 * 3,数组复制。
		 * 4,对两个数组进行元素的比较,判断两个数组是否相同。
		 * 5,将数组转成字符串。
		 */
		
		int[] arr = {34,21,67};
		System.out.println(Arrays.toString(arr));
		
		//将arr转成list集合。?如果数组中存储的是基本数据类型,那么转成集合,数组对象会作为集合中的元素存在。
		//数组中元素时引用数据类型时,转成,数组元素会作为集合元素存在。
		 List list1 = Arrays.asList(arr);
		 System.out.println(list1);
		
		
		
		
		String[] strs = {"hah","hehe","xixi"};
		boolean b = contains(strs,"hehe");
		System.out.println(b);
		//将数组转成list集合。asList
		/*
		 * 数组转成集合:就为了使用集合的方法操作数组中的元素。
		 * 但是不要使用增删等改变长度的方法。add remove  发生UnsupportedOperationException
		 */
		List list = Arrays.asList(strs);
		System.out.println(list.contains("hehe"));
		System.out.println(list.get(2));
		System.out.println(list.indexOf("hehe"));
//		list.add("java");//UnsupportedOperationException  数组长度的固定的,转成List集合长度也是固定的。
		
		
		
		
		//-------------------集合转成数组---------------------
		/*
		 * 为什么集合转成数组呢?
		 * 为了限制对元素的增删操作。
		 */
		Collection c = new ArrayList();
		c.add("haha1");
		c.add("haha2");
		c.add("haha3");
		c.add("haha4");
		/*
		 *  如果传递的数组的长度小于集合的长度,会创建一个同类型的数组长度为集合的长度。
		 *  如果传递的数组的长度大于了集合的长度,就会使用这个数组,没有存储元素的位置为null。
		 *  长度最好直接定义为和集合长度一致。
		 */
		String[] str_arr = c.toArray(new String[c.size()]);
		System.out.println(Arrays.toString(str_arr));

	}

	public static boolean contains(String[] strs,String key) {
	
		for (int i = 0; i < strs.length; i++) {
			if(strs[i].equals(key)){
				return true;
			}
		}
		
		return false;
	}
	
}

8 工具类

1,为了解决集合的更多需求。集合框架提供了Collections和Arrays两个工具类,方法都是静态的。

2,Collections是用于操作集合的工具类。

                                     常见方法:对List集合排序,二分查找,对Collection集合进行最值获取。

                                     对排序进行逆序,将非同步的集合转成同步的集合。

3,Arrays对数组操作的工具类:

                                     常见方法:对数组排序,二分查找,数组复制,将数组转成字符串等。

4,数组集合互转。

                            4.1将数组转成集合 Arrays.asList方法。

                                     目的:使用集合的方法操作数组元素。

                                     注意:不要使用集合的增删方法。因为数组转成List集合后长度是固定的。

                                          转成集合的数组中存储的元素最好是对象,如果是基本数据类型,会将这个数组作为元素存储到集合中。

                            4.2集合转成数组。

                                               Collection接口中的toArray方法。

                                               目的:限定对元素的增删,长度的改变。

 

9 Map

Map

         |--Hashtable:数据结构:哈希表。是同步的,不允许null作为键和值。被hashMap替代。

                   |--Properties:属性集,键和值都是字符串,而且可以结合流进行键值的操作。等到了IO流,你会更清楚。

         |--HashMap:数据结构:哈希表。不是同步的,允许null作为键和值。

                   |--LinkedHashMap:基于链表+哈希表。可以保证map集合有序(存入和取出的顺序一致)。

         |--TreeMap:数据结构:二叉树。不是同步的。可以对map集合中的键进行排序。

 

什么时候使用map集合呢?

分析问题时出现对应关系,毫不犹豫的想到map集合。

如果对应关系中出现了有序的数字,想到数组。

注意:如果对应关系个数不确定,还是以map为主。

9.1  Map特点和常用功能

Map集合特点;

1,内部存储的都是键key值value对。

2,必须要保证的键的唯一性。

 

Map常见功能。

         1,存储。v put(k,v);

         2,获取。v get(k);

         3,移除。v remove(k);

         4,Set keySet();

         5,Set> entrySet();

         6,Collection values();

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

public class MapDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Map map = new HashMap();

		map.put("星期一", "Monday");
		map.put("星期日", "Sunday");
		
		System.out.println("------------keySet方法的获取---------------");
//		System.out.println(map.get("星期一"));
		//怎么获取到所有的键呢?既然是所有的键,应该是一个集合,而且是一个单列集合。
		//list还是set呢?应该是set,因为map集合中键需要保证唯一性。
		//找到一个方法   Set keySet();获取map集合中的键的set集合。
		Set keySet = map.keySet();
		for(Iterator it= keySet.iterator(); it.hasNext() ; ){
			String key = it.next();
			String value = map.get(key);//通过键获取对应的值。
			System.out.println(key+"::"+value);
		}
		//使用foreach循环,进行遍历。
		for(String key : keySet){
			System.out.println(key+":::::"+map.get(key));
		}
		
		System.out.println("-----------entrySet方法获取----------------");
		
		/*
		 * Set entrySet():将map集合中映射关系存储到了Set集合中.
		 * 映射关系:其实就是指键和值的对应关系。其实就是夫妻的结婚证。
		 * 映射关系是什么类型的呢?  Map.Entry
		 */
		Set> entrySet = map.entrySet();
		Iterator> it = entrySet.iterator();
		//遍历Set中的映射关系对象。
		while(it.hasNext()){
			Map.Entry me = it.next();//取到了映射关系对象。
			//获取键。
			String key = me.getKey();
			//获取值。
			String value = me.getValue();
			System.out.println(key+"-----"+value);
		}
		
		/*
		 * 总结:map集合没有迭代器,取出元素的方式:将map集合转成单列结合,在使用单列集合的迭代器就可以了。
		 * map集合也不能直接被foreach循环遍历。
		 */
		for(Map.Entry me : map.entrySet()){
			String key = me.getKey();
			//获取值。
			String value = me.getValue();
			System.out.println(key+"--------"+value);
		}
		
		
		System.out.println("-----------获取所有值的方法 values()----------------");
		/*
		 * 获取所有的值,因为值不需要保证唯一性。所以返回类型时Collection。
		 * 姓名--归属地。对应关系,获取所有的归属地。values();
		 */
		
		//所有的英文星期。
		Collection values = map.values();
		for(String value : values){
			System.out.println("value:"+value);
		}
	}
}

9.2 HashMap

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

import cn.itcast.domain.Student;

public class HashMapTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		/*
		 * 练习一:
		 * 学生对象(姓名,年龄)都有自己的归属地,既然有对应关系。
		 * 将学生对象和归属地存储到map集合中。
		 * 注意:同姓名同年龄视为重复的键。
		 */
		
		//1,创建hashmap集合对象。
		Map map = new HashMap();
		
		//2,添加元素。
		map.put(new Student("lisi",28), "上海");
		map.put(new Student("wangwu",22), "北京");
		map.put(new Student("zhaoliu",24), "成都");
		map.put(new Student("zhouqi",25), "广州");
		map.put(new Student("wangwu",22), "南京");
		
		//3,取出元素。keySet  entrySet
//		Set keySet = map.keySet();
//		for(Student key : keySet){}
		for(Student key : map.keySet()){
			String value = map.get(key);
			
			System.out.println(key.toString()+"....."+value);
		}
		
	}

}

9.3  TreeMap

 

import java.util.Map;

import java.util.TreeMap;

 

importcn.itcast.api.c.comparator.ComparatorByName;

import cn.itcast.domain.Student;

 

public class TreeMapTest {

 

         /**

          * @param args

          */

         publicstatic void main(String[] args) {

                   /*

                    * 练习二: 学生对象(姓名,年龄)都有自己的归属地,既然有对应关系。将学生对象和归属地存储到map集合中。

                    * 注意:同姓名同年龄视为重复的键。按照学生的年龄进行从小到大的排序。 TreeMap。

                    *

                    * 如果要对学生按照姓名排序呢?

                    */

 

                   //1,创建TreeMap集合对象。

                   Map map = new TreeMap(new ComparatorByName());

 

                   //2,添加元素。

                   map.put(newStudent("lisi", 28), "上海");

                   map.put(newStudent("wangwu", 22), "北京");

                   map.put(newStudent("zhaoliu", 24), "成都");

                   map.put(newStudent("zhouqi", 25), "广州");

                   map.put(newStudent("wangwu", 22), "南京");

 

                   //3,取出所有元素,entrySet()

                   for(Map.Entry me : map.entrySet()){

                           

                            Studentkey = me.getKey();

                            Stringvalue = me.getValue();

                           

                            System.out.println(key+"::"+value);

                           

                   }

                  

         }

 

}

 

 

import java.util.Comparator;

 

import cn.itcast.domain.Student;

 

public class ComparatorByName implementsComparator {

 

         @Override

         publicint compare(Student o1, Student o2) {

                   inttemp = o1.getName().compareTo(o2.getName());

                   returntemp==0?o1.getAge() - o2.getAge() : temp;

         }

 

}

9.4 案例--获取字母出现的次数

import java.util.Map;
import java.util.TreeMap;

public class MapTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		/*
		 * 练习:
		 * "werertrtyuifgkiryuiop",获取字符串中每一个字母出现的次数。
		 * 要求返回结果个格式是  a(1)b(2)d(4)......;
		 * 思路:
		 * 1,获取到字符串中的每一个字母。
		 * 2,用字母取查表,如果查到了该字母对应的次数,就将这个次数+1后重新存回表中。
		 * 	如果没有查到呢?将该字母和1存到表中。
		 * 3,每一字母都查完表后,表中记录的就是所有字母出现的次数。
		 * 
		 * 字母和次数之间存在对应关系,而且字母是唯一性的,所以可以使用map集合做表进行查询。
		 * 通过结果发现 字母有顺序的,所以可以通过map集合中的treemap作为表。
		 * 
		 */
		
		String str = "awaa+acr=ebarct,btydui[efgkiryuiop";
		str = getCharCount(str);
		System.out.println(str);
	}

	/**
	 * 获取字符串中的字母出现次数。
	 * 
	 * @param str
	 * @return 返回一个每一个字母对应次数的字符串 格式  char1(count)char2(count).....;
	 */
	public static String getCharCount(String str) {
		
		//1,将字符串转成字符数组。
		char[] chs = str.toCharArray();
		
		//2,定义表。treemap.
		TreeMap map = new TreeMap();
		
		//3,遍历字符数组。
		for (int i = 0; i < chs.length; i++) {
			
			//判断必须是字母。
			if(!(chs[i]>='a' && chs[i]<='z' || chs[i]>='A' && chs[i]<='Z')){
				continue;
			}
			
			//4,将遍历到的字母作为键去查map这个表。获取对应的次数。
			Integer value = map.get(chs[i]);
			
			//5,有可能要查询的字母在表中不存在对应的次数,需要判断。
			//如果返回是null,说明字母没有对应的次数。就将这个字母和1存储到表中。
			if(value == null){
				
				//将字母和1存储。
				map.put(chs[i],1);
			}else{
				
				//否则,说明有对应的次数对次数自增。将字母和新的次数存储到表中。
				value++;
				map.put(chs[i],value);
			}
			/*
			 //两个if判断,选择哪个都行。
			int count = 0;
			if(value!=null){
				count = value;//用count记录次数。
			}
			count++;//自增。
			map.put(chs[i], count);
			*/
		}
		
		//将map集合中的键值转成   格式是  a(1)b(2)d(4)......
		
	
		return mapToString(map);
	}

	/*
	 * 将map集合中的键值转成   格式是  a(1)b(2)d(4)......
	 * map中有很多数据,无论是多少个,什么类型,最终都变成字符串。
	 * StringBuffer 这个容器就符合这个需求。如果是单线程,建议使用StringBuilder。
	 * 
	 */
	private static String mapToString(Map map) {
		//1,明确容器。
		StringBuilder sb = new StringBuilder();
		
		//2,遍历map集合。
		for(Character key  : map.keySet()){
			Integer value = map.get(key);
			
			sb.append(key+"("+value+")");
		}
		return sb.toString();
	}
}


 







你可能感兴趣的:(java,java,黑马程序员)