黑马程序员_集合框架,泛型,Collections工具类

------- android培训java培训、期待与您交流! ----------

为什么出现集合类?

    面向对象语言对事物的体现都是以对象的形式,所以为了方便很多个对象的操作,
    就对对象进行存储,集合就是存储对象最常用的一种方式。

数组和集合类同时容器,有什么不同。
    数组虽然也可以存储对象,但是长度是固定的。     
    集合长度是可变的。
    数组中可以存储基本数据类型,集合只能存储对象。

集合类的特点。
    集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

add方法的参数类型是Object,以便于接受任意类型的对象。
集合中存储的都是对象的引用(地址)。

那我们怎么从集合中取出各个元素呢---->用迭代器?

什么是迭代器呢?
其实就是集合的取出元素的方式。
import java.util.*;

class CollectionDemo 
{
	public static void main(String[] args) 
	{
		method_get();
	}
	
	public static void method_get()
	{
		ArrayList al = new ArrayList();//创建了一个集合并往里面添加对象。
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		
		/*
		Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。

		while(it.hasNext())
		{
			sop(it.next());
		}*/
		for (Iterator it = al.iterator();it.hasNext() ; )
		{
			sop(it.next());
		}
	}

	public static void method_2()
	{
		ArrayList al1 = new ArrayList();
		al1.add("java01");
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");

		ArrayList al2 = new ArrayList();
		al2.add("java01");
		al2.add("java02");
		al2.add("java05");
		al2.add("java06");

		//al1.retainAll(al2);取交集,al1中只会保留和al2中相同的元素。没有交集则会为空。
		al1.removeAll(al2);//移除相同的元素。
		sop("al1:"+al1);
		sop("al2:"+al2);
	}

	public static void bese_method()
	{
		//创建一个集合容器,使用collection接口的子类,ArrayLise。
		ArrayList al = new ArrayList();

		//添加元素。
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");

		//打印原集合
		sop("原集合:"+al);//打印的是[java01, java02, java03, java04]

		//删除元素
		al.remove("java02");
		//al.clear();清空集合。

		//判断元素。
		sop("java03是否存在:"+al.contains("java03"));
		sop("集合是否为空:"+al.isEmpty());

		//打印改变后的集合
		sop(al);

		//获取个数,集合长度
		//sop("size:"+al.size());//打印的是size:4
	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

Collection 
|--List:元素是有序的,元素可以重复,因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的是链表数据结构。特点:增删很快,查询的时候稍慢。
|--Vector:底层是数组数据结构(JDK1.0版本)线程同步。和ArrayList(JDK1.2)一样的结构。被ArrayList替代了。
|--set:元素师无序的,元素不可以重复,该集合无索引。

List:
特有方法,凡是可以操作角标的方法都是该体系特有方法。
add(index,element);
addAll(index,Collection);
remove(index);
set(index,element);
get(index);
subList(from,to);
listIterator();

List集合特有的迭代器,ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常。
所以呢,在迭代时,只能用迭代器的方法操作元素,可以Iterator方法是有限的,
只能对元素进行判断,取出,修改操作,
如果想要其他的操作如添加修改等,就需要使用其子接口,ListIterator.
该接口只能通过List集合的listIterator方法获取。

hasNext();正向的遍历有没有下一个元素,hasPrevious();逆向的遍历有没有前一个元素。
import java.util.*;
class ListDemo
{
	public static void method()
	{
		ArrayList al = new ArrayList();
		//添加元素。
		al.add("java01");
		al.add("java02");
		al.add("java03");
		sop("原集合是:"+al);
		//在制定位置添加元素。
		al.add(1,"java09");
		
		//al.remove(2);删除指定位置的元素。
		
		//al.set(2,"java007");修改元素。
		//通过角标获取元素。
		sop("get(1)="+al.get(1));
		//获取所有元素的几种方法。
		for (int x=0;x<al.size() ;x++ )
		{
			sop("al("+x+")"+al.get(x));
		}
		sop(al);
		Iterator it1 = al.iterator();
		while(it1.hasNext())
		{
			sop("next:"+it1.next());
		}
		for (Iterator it = al.iterator();it.hasNext() ; )
		{
			sop("next:"+it.next());
		}
		//通过indexOf获取对象的位置。
		sop("index="+al.indexOf("java02"));
		
		List sub = al.subList(1,3);
		sop("sub" + sub);
	}
	public static void main(String[] args) 
	{
		//演示列表迭代器。
		ArrayList al = new ArrayList();
		//添加元素。
		al.add("java01");
		al.add("java02");
		al.add("java03");
		sop("原集合是:"+al);
		//在迭代过程中,准备添加或者删除元素。
		for (ListIterator li = al.listIterator();li.hasNext() ; )
		{
			Object obj = li.next();
			if (obj.equals("java02"))
			{
				//li.add("java009");
				li.set("java008");
			}
		}
		sop(al);
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

LinkedList:特有方法:
addFirst();
addLast();

getFirst();
getLast();
获取元素,但是不删除元素。如果集合中没有元素会出现NoSuchElementException
sop(link.getFirst());

removeFirst();
removeLast();
获取元素,但是元素被删除。如果集合中没有元素会出现NoSuchElementException
sop(link.removeFirst());打印java04

在JDK1.6出现了替代方法。

offerFirst();
offerLast();

PeekFirst();
PeekLast();
获取元素,但是不删除元素。如果集合中没有元素会出现null

pollFirst();
pollLast();
获取元素,但是元素被删除。如果集合中没有元素会出现null
import java.util.*;
class LinkedListDemo 
{
	public static void main(String[] args) 
	{
		LinkedList link = new LinkedList();
		link.addLast("java01");
		link.addFirst("java02");
		link.addFirst("java03");
		link.addFirst("java04");
		//sop(link);
		
		//sop(link.getLast());打印java01
		//sop(link.removeFirst());打印java04
		//sop("size="+link.size());
		//取出全部元素。
		while(!link.isEmpty())
		{
			sop(link.removeFirst());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

**练习:
使用LinkedList模拟一个堆栈汇总队列数据结构。
堆栈:先进后出。
队列:先进先出。First in First out  FIFO
import java.util.*;
class DuiLie
{
	private LinkedList link;
	DuiLie()
	{
		link = new LinkedList();
	}
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
	public Object myGet()
	{
		return link.removeFirst();//可以通过removeFirst(),removeLast()来控制先进先出或者是先进后出
	}
	public boolean isNull()
	{
		return link.isEmpty();
	}
}
class LinkedListTest 
{
	public static void main(String[] args) 
	{
		DuiLie dl = new DuiLie();
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");
		
		while(!dl.isNull())
		{
			sop(dl.myGet());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

ArrayList练习
取出ArrayList中的重复元素。
在迭代中next()调用一次,就要hasNext()判断一次。
import java.util.*;
class ArrayListTest 
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java03");
		sop(al);
		al = singleElement(al);
		sop(al);
	}
	public static ArrayList singleElement(ArrayList al)
	{
		ArrayList newAl = new ArrayList();//定义一个集合来装不重复元素。
		for (Iterator it = al.iterator();it.hasNext() ; )
		{
			Object obj = it.next();
			if (!newAl.contains(obj))//当新集合里面不包含遍历到的元素的时候就将该元素添加到新集合里面
			{
				newAl.add(obj);
			}
		}
		return newAl;
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
|--Set:元素是无序的(存入和取出),元素不可以重复。
|--HashSet:底层数据结构是哈希表。
import java.util.*;
class HashSetDemo 
{
	public static void main(String[] args) 
	{
		HashSet hs = new HashSet();
		hs.add("java01");
		hs.add("java02");
		hs.add("java03");
		hs.add("java04");
		for (Iterator it = hs.iterator();it.hasNext() ; )
		{
			sop(it.next());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

ArrayList:
判断元素和删除元素只依赖equals。
HashSet:
判断元素和删除元素先依赖hashCode,当hashCode相同在依赖equals。

Set:无序,不重复。
|--HashSet: 数据结构是哈希表,线程非同步。
保证元素的唯一性原理:判断元素的hasCode值是否相同,
如果相同,还会继续判断元素的equals方法,是否为true。
|--TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元素唯一性的依据是:
cpmpareTo方法return 0.

TreeSet排序的第一种方式:让元素自身具备比较性,
元素需要实现 comparable接口,覆盖compareTo方法。
这种方式也称为元素的自然顺序,或者叫做默认顺序。

TreeSet的第二种排序方式。
当元素自身不具备比较性是,或者具备的比较性不是所需要的。
这时候需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
二叉树的示意图:

需求:
往TreeSet里面存储自定义学生对象。
想按照学生的年龄进行排序。

排序时,当主要条件相同时,一定要判断一下次要条件。

import java.util.*;
class TreeSetDemo 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet();
		ts.add(new Student("lishi02",22));
		ts.add(new Student("lishi07",20));
		ts.add(new Student("lishi09",19));
		ts.add(new Student("lishi01",19));
		for (Iterator it = ts.iterator();it.hasNext() ; )
		{
			Student stu = (Student)it.next();
			sop(stu.getName()+"--"+stu.getAge());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class Student implements Comparable//该接口强制让学生具备比较性。
{
	private String name;
	private int age;
	
	public int compareTo(Object obj)
	{
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		if (this.age>s.age)
			return 1;
		if (this.age==s.age)//当年龄相同的时候
		{
			
			return this.name.compareTo(s.name);//一定要判断一次姓名是否相同。
		}
		return -1;
	}
	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

当元素自身不具备比较性。或者具备的比较性不是所需要的。
这时需要让容器自身具备比较性。
就定义了一个比较器,将比较器对象作为参数传递个TreeSet集合的构造函数。
当两种方式都存在比较性时,以比较器为主。

定义一个类,实现Comparetor接口,覆盖compare方法。
import java.util.*;
class TreeSetDemo2 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new MyCompare());//将自定义的比较器传入学生对象中。
		ts.add(new Student("lishi02",22));
		ts.add(new Student("lishi07",20));
		ts.add(new Student("lishi09",19));
		ts.add(new Student("lishi02",19));
		for (Iterator it = ts.iterator();it.hasNext() ; )
		{
			Student stu = (Student)it.next();
			sop(stu.getName()+"--"+stu.getAge());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);//会输出非重复对象。
	}
}
class MyCompare implements Comparator//自定义一个比较器,继承Comparator复写其中的compare方法
{
	public int compare(Object o1,Object o2)//重写该方法让其具有自己想要的比较方式。
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
			return s1.getAge()-s2.getAge();//返回正数负数零。与返回-1,0,1一样
		return num;
	}
}
class Student implements Comparable//该接口强制让学生具备比较性。
{
	private String name;
	private int age;
	
	public int compareTo(Object obj)//重写compareTo方法、自定义排序条件
	{
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		if (this.age>s.age)
			return 1;
		if (this.age==s.age)//当年龄相同的时候
		{
			
			return this.name.compareTo(s.name);//一定要判断一次姓名是否相同。
		}
		return -1;
	}
	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

练习:按照字符串长度排序。
字符串本身具备比较性,但是它的比较性不是所需要的。
这时这能使用比较器。
import java.util.*;
class TreeSetTest 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new StringLengthComparator());
		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("cba");
		ts.add("z");
		ts.add("hahaha");
		for (Iterator it = ts.iterator();it.hasNext() ; )
		{
			sop(it.next());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class StringLengthComparator implements Comparator//自定义的比较器
{
	public int compare(Object o1,Object o2)
	{
		String s1 = (String)o1;
		String s2 = (String)o2;
		if(s1.length() == s2.length())//当长度一样的时候需要判断内容。
			return s1.compareTo(s2);//判断字符串的内容是否一样。
		return new Integer(s1.length()).compareTo(s2.length());//返回s1.s2比较的compareTo结果。
	}
}

泛型:JSK1.5版本之后出现的新特性。用于解决安全问题,是一个类型安全机制。

好处:
1、讲运行时期出现问题ClassCastException,转移到了编译时期。
方便于程序员解决问题,让运行时期问题减少,安全。
2、避免了强制转换的麻烦。

泛型格式:通过<>来定义要操作的引用数据类型。

在使用java提供的对象时,什么时候使用泛型呢?
通常在集合框架中很常见。
只要见到<>就要定义泛型。
其实<>就是用来接收类型的。

当使用结合时,将集合中要存储的数据类型作为参数传递到<>中即可。
import java.util.*;
class GenericDemo2 
{
	public static void main(String[] args) 
	{
		TreeSet<String> ts = new TreeSet<String>(new LenComparator());//提示该类接受的是String类型。
		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("cba");
		ts.add("z");
		ts.add("hahaha");
		for (Iterator<String> it = ts.iterator();it.hasNext() ; )
		{
			String s = it.next();
			System.out.println(s);
		}
	}
}
class LenComparator implements Comparator<String>//Comparator里面也有泛型类避免了下面的强转。
{
	public int compare(String o1,String o2)
	{
		//String s1 = (String)o1;
		//String s2 = (String)o2;
		//想要倒叙就把o1,o2换个位置就行了。
		if(o1.length() == o2.length())//当长度一样的时候需要判断内容。
			return o1.compareTo(o2);//判断字符串的内容是否一样。
		return new Integer(o1.length()).compareTo(o2.length());//返回s1.s2比较的compareTo结果。
	}
}

什么时候定义泛型类?
当类中,要操作的引用数据类型不确定的时候,
早期,定义Object来完成扩展。
现在定义泛型来完成扩展。

泛型类定义的泛型,在整个类中有效,如果被方法使用,
那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
为了让不同方法可以操作不同类型,而且类型还不确定。
那么可以将泛型定义在方法上。

特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。

? 通配符。也可以理解为占位符。
泛型的限定:
? extends E: 可以接受E类型或者E的子类型。上限。
? super E:可以接受E类型或者E类型的父类。下限。
import java.util.*;
class GenericDemo6 
{
	public static void main(String[] args) 
	{
		ArrayList<Person> al = new ArrayList<Person>();
		al.add(new Person("abcd1"));
		al.add(new Person("abcd2"));
		al.add(new Person("abcd3"));
		ArrayList<Student> al1 = new ArrayList<Student>();
		al1.add(new Student("abcd--1"));
		al1.add(new Student("abcd--2"));
		al1.add(new Student("abcd--3"));
		printColl(al);
		printColl(al1);
	}
	public static void printColl(ArrayList<? extends Person> al)//? extends Person上限为Person也可以向下限定? extends Student
	{
		for (Iterator<? extends Person> it = al.iterator();it.hasNext() ; )
		{
			System.out.println(it.next().getName());
		}
	}
}
class Person
{
	private String name;
	Person(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return name;
	}
}
class Student extends Person
{
	 Student(String name)
	{
		 super(name);
	}
}

Map集合:
Map集合:该集合存储键值对。一对一对往里存,而且要保证键的唯一性。
1、添加。
put(K key,V value)
putAll(Map<? extends k,? extends V> m)
2、删除。
clear();
remove(Key k);
3、判断。
containsKey(Object key)
containsValue(Object value)
isEmpty()
4、获取。
get(Object key)
size()获取长度。
values()获取里面的值。

entrySet()返回此映射中包含的映射关系的 Set 视图
KeySet() 返回此映射中包含的键的 Set 视图。

Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0效率低
|--hashMap:底层是哈希表数据结构,允许使用null键null值,该集合石不同步的。JDK1.2效率高。
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。
import java.util.*;
class MapDemo 
{
	public static void main(String[] args) 
	{
		Map<String,String> map = new HashMap<String,String>();
		//添加元素。
		map.put("01","zhangsan1");
		map.put("01","wangwu");//当存入相同键的时候新值会替代原来的值。打印01=wangwu;并返回被覆盖的值zhangsan1;
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		map.put(null,"haha");//在hashMap中可以将null作为键,返回具体的值。
		map.put("haha",null);//在hashMap中可以将null作为值,作为具体键的值。hashTable就不行。
		System.out.println("containsKey:"+map.containsKey("02"));//打印true看map里面是否有02。
		//System.out.println("remove:"+map.remove("02"));打印的是remove:zhangsan2删除了键后会返回相对应的值。
														//当remove的值不存在的时候会输出null。	
		
		System.out.println("get:"+map.get("02"));//当获取的key不存在的时候会返回null,可用于判断该值是否存在于该map中。
		
		//获取map集合中所以得值。
		Collection<String> coll = map.values();
		System.out.println(coll);//打印的是{null=haha, haha=null, 01=zhangsan1, 02=zhangsan2, 03=zhangsan3}。
		
		System.out.println(map);//打印出来的是{01=zhangsan1, 03=zhangsan3}
	}
}

map集合的两种取出方式:

1、KeySet:
       将map中所有的键存到Set集合中,因为Set集合具备迭代器。 所以可以通过迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。


2、entrySet:
          将map集合中的映射关系存入到了set集合中, 而这个关系的数据类型就是:Map.Entry。


import java.util.*;
class MapDemo2 
{
	public static void main(String[] args) 
	{
		Map<String,String> map = new HashMap<String,String>();
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		map.put("01","zhangsan1");
		map.put("04","zhangsan4");
		//将Map集合中的映射关系取出,存入到Set集合中。
		Set<Map.Entry<String,String>> entrySet = map.entrySet();
		Iterator<Map.Entry<String,String>> it = entrySet.iterator();
		while(it.hasNext())
		{
			 Map.Entry<String,String> me = it.next();
			 String key = me.getKey();
			 String value = me.getValue();
			 System.out.println(key+"--"+value);
		}
		/*用KeySet方法取出map里面的数据。
		//先获取map集合中的所有键的Set集合,KeySet();
		Set<String> keySet = map.keySet();
		//有了Set集合,就可以获取其迭代地。
		for (Iterator<String> it = keySet.iterator();it.hasNext() ; )
		{
			String key = it.next();
			//有了键可以通过map集合的get方法获取其对应的值。
			String value = map.get(key);
			System.out.println(key+"--"+value);
		}
		*/
	}
}

示例:
每一个学生都有对应的归属地,
学生Student,地址String.
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生,保证学生的唯一性。

1、描述学生。

2、定义map容器,将学生作为键,地址作为值。存入。

3、获取map集合中的元素。
import java.util.*;
class Student implements Comparable<Student>
{
	private String name;
	private int age;
	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	//可能存到二叉树里面所以必须要复写comparaTo方法。
	public int compareTo(Student s)
	{
		//按照年龄排序
		int num = new Integer(this.age).compareTo(new Integer(s.age));
		if(num==0)//当年龄一样的时候比较姓名
			return this.name.compareTo(s.name); 
		return num;
		/*按照姓名排序。
		if(this.name.compareTo(s.name)==0)//如果姓名一样的时候比较年龄
			return new Integer(this.age).compareTo(new Integer(s.age))
		return this.name.compareTo(s.name); 
		*/
	}
	//可能存到hashMap里面去就必须复写hashCode()和equals()
	public int hashCode()
	{
		return name.hashCode()+age*34;
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配");
		Student s = (Student)obj;
		return this.name.equals(s.name) && this.age == s.age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String toString()
	{
		return name + ":" + age;
	}
}
class MapTest 
{
	public static void main(String[] args) 
	{
		HashMap<Student,String> hm = new HashMap<Student,String>();
		hm.put(new Student("lisi1",21),"beijing");
		hm.put(new Student("lisi1",21),"tianjing");
		hm.put(new Student("lisi2",22),"shanghai");
		hm.put(new Student("lisi3",23),"nanjing");
		hm.put(new Student("lisi4",24),"wuhan");
		/*
		//第一种取出方式:
		Set<Student> keySet = hm.keySet();
		for (Iterator<Student> it = keySet.iterator();it.hasNext() ; )
		{
			Student stu = it.next();
			String addr = hm.get(stu);
			System.out.println(stu+"--"+addr);
		}*/
		//第二种取出方式
		Set<Map.Entry<Student,String>> entrySet = hm.entrySet();
		for (Iterator<Map.Entry<Student,String>> it1 = entrySet.iterator();it1.hasNext() ; )
		{
			Map.Entry<Student,String> me = it1.next();
			Student key = me.getKey();
			String value = me.getValue();
			System.out.println(key+"--"+value);
		}
	}
}

需求:对学生对象的年龄进行升序排序。

因为数据是以键值对形势存在的。
所以需要使用可以排序的Map集合。TreeMap。
修改后的代码:

import java.util.*;
class MapTest2 
{
	public static void main(String[] args) 
	{
		TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator());
		tm.put(new Student("alisi3",23),"nanjing");
		tm.put(new Student("slisi1",21),"beijing");
		tm.put(new Student("slisi1",21),"tianjing");
		tm.put(new Student("dlisi2",22),"shanghai");
		tm.put(new Student("flisi4",24),"wuhan");
		Set<Map.Entry<Student,String>> entrySet = tm.entrySet();
		for (Iterator<Map.Entry<Student,String>> it = entrySet.iterator();it.hasNext() ; )
		{
			Map.Entry<Student,String> me = it.next();
			Student stu = me.getKey();
			String value = me.getValue();
			System.out.println(stu+"--"+value);
		}
	}
}
class StuNameComparator implements Comparator<Student>
{
	public int compare(Student s1,Student s2)
	{
		if(s1.getName().compareTo(s2.getName()) ==0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		return s1.getName().compareTo(s2.getName());
	}
}
//如果不想用Student里面自带的年龄排序而想要姓名排序,那么就自定义一个比较器。
class Student implements Comparable<Student>
{
	private String name;
	private int age;
	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	//可能存到二叉树里面所以必须要复写comparaTo方法。
	public int compareTo(Student s)
	{
		//按照年龄排序
		int num = new Integer(this.age).compareTo(new Integer(s.age));
		if(num==0)//当年龄一样的时候比较姓名
			return this.name.compareTo(s.name); 
		return num;
		/*按照姓名排序。
		if(this.name.compareTo(s.name)==0)//如果姓名一样的时候比较年龄
			return new Integer(this.age).compareTo(new Integer(s.age))
		return this.name.compareTo(s.name); 
		*/
	}
	//可能存到hashMap里面去就必须复写hashCode()和equals()
	public int hashCode()
	{
		return name.hashCode()+age*34;
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配");
		Student s = (Student)obj;
		return this.name.equals(s.name) && this.age == s.age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String toString()
	{
		return name + ":" + age;
	}
}

练习:
"sdfgzxcvaasdfxcvdf"获取该字符串中的字母出现的次数。
希望打印结果a(1)c(2).......

通过结果发现。每一个字母都有对应的次数。
说明字母和次数之间都有映射关系。

当发现有映射关系的时候,可以选择map集合。
因为map集合中存放的就是映射关系。

什么时候使用map集合呢?
当数据之间存在着映射关系时,就要先想到map集合。

思路:
1、将字符串转换成字符数组,因为要对每一个字母进行操作。

2、定义一个map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。

3、遍历这个字符数组。将每一个字母作为键去查map集合。
如果返回null就将该字母和1存入map集合中,
如果返回不是空,说明该字母在map集合中已经存在并有对应的次数。
那么就获取该次数并进行自增,然后将该字母和子增后的次数存入到map集合中,
覆盖掉原来键对应的值。

4、将map集合中的数据变成制定的字符串形式返回。
import java.util.*;
class MapTest3 
{
	public static void main(String[] args) 
	{
		String s = charCount("aabfcdabcdefa");
		System.out.println(s);
	}
	public static String charCount(String str)
	{
		char[] chs = str.toCharArray();
		int count = 0;
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		for (int x=0;x<chs.length ;x++ )
		{
			//当不是a~z和A~Z之间的数的时候直接跳出本次循环继续下一次循环。
			if(!(ch[x]>='a' && ch[x]>='z' || ch[x]>='A' && ch[x]>='Z'))
				continue;
			Integer value = tm.get(chs[x]);//获取chs[x]的值
			if(value!=null)当//value不为空的时候
				count = value;记录住该值自增
			count++;//当为空的时候自增并存进去。
			tm.put(chs[x],count);
			count = 0;
		}
		StringBuilder sb = new StringBuilder();//用来装将要输出的字符
		Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
		for (Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator() ;it.hasNext() ; )
		{
			Map.Entry<Character,Integer> me = it.next();
			Character key = me.getKey();
			Integer value = me.getValue();
			sb.append(key+"(" + value+")");
		}
		
		return sb.toString();
	}
}

map集合扩展知识。

map集合被使用是因为具备映射关系。

一个学校有多个教室,每个教室都有学生,每个不同名称的教室都有相同的1.2.3号学生
一个键对应的多个映射。
import java.util.*;
class MapDemo3
{
	public static void main(String[] args) 
	{
		HashMap<String,HashMap<String,String>> czbk = new HashMap<String,HashMap<String,String>>();//这是传智播客学校集合
		
		HashMap<String,String> yure = new HashMap<String,String>();//这时预热班集合
		HashMap<String,String> jiuye = new HashMap<String,String>();//这时就业班集合
		czbk.put("yureban",yure);
		czbk.put("jiuye",jiuye);	
		yure.put("01","zhangsan");
		yure.put("02","lisi");
		jiuye.put("01","wangwu");
		jiuye.put("02","zhaoliu");
		//遍历czbk集合,获取所有的教室。
		Set<String> keySet = czbk.keySet();
		for (Iterator<String> it = keySet.iterator();it.hasNext() ; )
		{
			String roomName = it.next();
			HashMap<String,String> room = czbk.get(roomName);
			System.out.println(roomName);
			getStuInfo(room);
		}
	}
	
	public static void getStuInfo(HashMap<String,String> roomMap)
	{
		Set<String> keySet = roomMap.keySet();
		for (Iterator<String> it = keySet.iterator();it.hasNext() ; )
		{
			String id = it.next();
			String name = roomMap.get(id);
			System.out.println(id+"-"+name);
		}
	}
}

集合框架的工具类。

Collections:max.sort,binarySearch

import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{
		binarySearchDemo();
	}
	public static void binarySearchDemo()
	{
		List<String> list = new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		<span style="color:#ff0000;">Collections.sort(list);</span>//排序后为[aaa, abcd, kkkkk, qq, z, zz]
		System.out.println(list);
		//int index = Collections.binarySearch(list,"aaa");//索引位置为0
		//int index = Collections.binarySearch(list,"aaaa");如果需要找的数("aaaa")不存在则返回的为(-(插入点)-1)aaaa就为-2,
	}
	public static void maxDemo()
	{
		List<String> list = new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		String max = <span style="color:#ff0000;">Collections.max</span>(list/*,new StrLenComparator()*/);//查找自然数讯的最大值打印z,当加上自定义比较器的时候查找的是最大长度。
		System.out.println("max:"+max);
	}
	public static void sortDemo()
	{
		List<String> list = new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		<span style="color:#ff0000;">//Collections.sort(list);</span>
		Collections.sort(list,new StrLenComparator());//自定义排序。
		System.out.println(list);//按照自然排序打印[aaa, abcd, kkkkk, z, zz];
	}
}
class StrLenComparator implements Comparator<String>
{
	public int compare(String s1,String s2)
	{
		return s1.length()-s2.length();//按照长度排序,s1.length>s2.length返回正数,<返回负数,==返回0。
	}
}

Collections.reverseOrder()

import java.util.*;
//在TreeSet中想要倒叙可以复写compatator比较器。
class strComparator implements Comparator<String>
{
	public int compare(String s1,String s2)
	{
		//return s1.compareTo(s2);默认的排序
		return s2.compareTo(s1);//想要的倒叙
	}
}
//按照长度排序
class StrLenComparator implements Comparator<String>
{
	public int compare(String s1,String s2)
	{
		return s1.length()-s2.length();//按照长度排序,s1.length>s2.length返回正数,<返回负数,==返回0。
		//return s2.length()-s1.length();//按照从长到短!顺序。
	}
}
class CollectionDemo2
{
	public static void main(String[] args) 
	{
		orderDemo();
	}
	
	public static void orderDemo()
	{
		TreeSet<String> ts = new TreeSet<String>(<span style="color:#ff0000;">Collections.reverseOrder(new StrLenComparator())</span>);//传一个比较顺序,用reverseOrder()直接给你强行反转。
		//TreeSet<String> ts = new TreeSet<String>(new strComparator());//自己重写的反转方法。
		//TreeSet<String> ts = new TreeSet<String>(<span style="color:#ff0000;">Collections.reverseOrder()</span>);//Collection工具类的反转方法。
		ts.add("abcde");
		ts.add("aaa");
		ts.add("k");
		ts.add("cc");
		for (Iterator it = ts.iterator();it.hasNext() ; )
		{
			System.out.println(it.next());//默认的比较方法
		}
	}
	public static void replaceAllDemo()
	{
		List<String> list = new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		System.out.println(list);
		<span style="color:#ff0000;">Collections.replaceAll(list,"aaa","pp");//原理就是找到角标去set(index,"pp")将aaa换成pp</span>
		System.out.println(list);
		Collections.reverse(list);
		System.out.println(list);
	}
	//fill方法可以将list集合中所有元素替换成制定元素。
	public static void fillDemo()
	{
		List<String> list = new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		System.out.println(list);
		Collections.fill(list,"qq");
		System.out.println(list);
	}

Arrays:用于操作数组的工具类。里面都是静态方法!

asList:将数组变成集合。

import java.util.*;
class ArraysDemo 
{
	public static void main(String[] args) 
	{
		/*
		int[] arr = {2,4,5};
		System.out.println(Arrays.toString(arr));//将数组变成字符串。*/
		String[] arr = {"abc","cc","kkkk"};
		List<String> list = Arrays.asList(arr);//把数组变成集合。
		/*
		那数组变成List集合有什么好处啊?
		可以使用集合的思想和方法来操作数组中的元素。
		注意:将数组变成集合,不可以使用集合的增删方法。
		因为数组的长度是固定的。 
		contains.
		get.
		indexOf()
		subList();
		如果你增删,那么会发生UnsupportedOperationException.不支持操作异常。
		*/
		System.out.println(list);
		//int[] nums = {2,4,5};//会将整个数组作为集合中的元素。
		Integer[] nums = {2,4,5};
		List<Integer> li = Arrays.asList(nums);
		/*
		如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。
		如果数组中的元素,都是基本数据类型,那么会将该数组作为集合中的元素存在。
		*/
		System.out.println(li);
	}
}


集合变数组:CollectionToArray
import java.util.*;
class CollectionToArray 
{
	public static void main(String[] args) 
	{
		ArrayList<String> al = new ArrayList<String>();
		al.add("abc1");
		al.add("abc2");
		al.add("abc3");
		//String[] arr = al.toArray(new String[0]);//打印[abc1, abc2, abc3]。
		String[] arr = al.toArray(new String[5]);//打印[abc1, abc2, abc3, null, null]。
		//String[] arr = al.toArray(new String[al.size[]]);
		/*
		1、制定类型的数组到底要定义多长呢?
		当制定类型的数组长度小于了集合的长度size,那么该方法内部会创建一个新的数组,长度为集合的size.
		当制定类型的数组长度大于了集合的长度size,就不会创建数组,而是使用传递进来的数组。
		所以创建一个刚刚好的数组最优。
		2、为什么要将集合变数组。
		为了限定对元素的操作:不需要进行增删了。
		*/
		System.out.println(Arrays.toString(arr));
	}
}

高级for循环。

格式:
for(数据类型 变量名:被遍历的集合(Collection)或者数组;)
{
}

对集合进行遍历。
只能获取集合元素,但是不能对集合进行操作。

迭代器除了遍历,还可以进行remove集合中元素的动作。
如果使用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。

传统for循环和高级for循环有什么区别呢?
高级for有一个局限性。必须有被遍历的目标。

建议在遍历数组的时候,还是希望用传统for。因为传统for可以定义角标。

import java.util.*;
class ForEachDemo 
{
	public static void main(String[] args) 
	{
		ArrayList<String> al = new ArrayList<String>();
		al.add("abc1");
		al.add("abc2");
		al.add("abc3");
		for(String s:al)
		{	
			//s = "kk";加上该句代码也打印原集合,不能修改原集合指向的值。
			System.out.println(s);//集合也行。
		}
		int[] arr = {3,5,1};
		for (int i:arr)
		{
			System.out.println("i-"+i);//集合也行
		}
		HashMap<Integer,String> hm = new HashMap<Integer,String>();
		hm.put(1,"a");
		hm.put(2,"b");
		hm.put(3,"c");
		
		//第一种
		Set<Integer> keySet = hm.keySet();
		for (Integer i:keySet)
		{
			System.out.println(i+"--"+hm.get(i));
		}
		//第二种
		//Set<Map.Entry<Integer,String>> entrySet = hm.entrySet();
		//for(Map.Entry<Integer,String> me : entrySet)简写成一下格式。
		for(Map.Entry<Integer,String> me : hm.entrySet())
		{
			System.out.println(me.getKey()+"---"+me.getValue());
		}
	}
}

JDK 1.5 之后出现的新特性.
可变参数:
方法的可变参数,
在使用时注意:可变参数一定要定义在参数列表的最后面。
class ParamMethodDemo 
{
	public static void main(String[] args) 
	{
		show(2,5,4,8);
	}
	
	/*
	可变参数。
	只要将要操作的元素作为参数传递即可,隐式的将这些参数封装成了数组。
	*/
	public static void show(int... arr)
	{
		System.out.println(arr.length);
	}
}

StaticImport 静态导入:
当类名重名是,需要知道具体的包名。
当方法重名时,制定具备书所的对象或者类。 StaticImport 静态导入:
当类名重名是,需要知道具体的包名。
当方法重名时,制定具备书所的对象或者类。
import java.util.*;
import static java.util.Arrays.*;
import static java.lang.System.*; //导入了System类中的所有静态成员。
class StaticImportDemo 
{
	public static void main(String[] args) 
	{
		out.println("hahah");
		int[] arr = {3,1,5};
		Arrays.sort(arr);
		int index = binarySearch(arr,1);
		out.println(Arrays.toString(arr));
		System.out.println("Index="+index);
	}
}


------- android培训java培训、期待与您交流! ----------

详细请查看:www.itheima.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值