java类集整理collection map iterator listiterator list set enumeration
JAVA类集
1 、课程名称:JAVA类集
类集的作用、Collection、Map、Iterator、ListIterator、List、Set、Enumeration、二叉树算法
JAVA SE的最重要四块知识:面向对象、类集、JAVA IO、数据库编程
2 、知识点
2.1 、上次课程的主要知识点
1 、IO操作
BufferedReader:一次性读取数据
PrintStream:打印流
字节流:InputStream、OutputStream
File类
2 、对象序列化
2.2 、本次预计讲解的知识点
1 、类集的作用
2 、单值集合:Collection、List、Set
3 、二元偶集合:Map
4 、输出:Iterator、ListIterator、Enumeration
5 、类集的作用
3 、具体内容
3.1 、类集的作用
类集:就是一个动态的对象数组。
对象数组:可以保存一组对象,但是其本身有长度的限制。
类集可以保存一组对象,但是此保存没有长度的限制。
在JAVA中类集的操作都在java.util包中,本身也分为两种操作形式:
1 、存放单值的类集,最大的接口是Collection,每次可以存放一个值。但是其下又分为两个子接口:
List接口:表示可以重复,插入的顺序即为输出顺序
Set接口:不能够有重复元素
List接口在实际中应用较为广泛
主要操作方法:
添加一个对象: public boolean add(Object obj)
清空里面的所有内容: public void clear() ;
测试集合中是否包含指定元素: boolean contains(Object o)
判断集合是否为空: public boolean isEmpty()
从集合中删除指定内容: public boolean remove(Object o)
取得集合中大小: public int size()
将集合变为对象数组: public Object[] toArray()
将集合变为Iterator实例: public Iterator < E > iterator()
对于整个Collection集合,只允许从前向后输出,没有从后向前输出的功能。
讨论:
是使用Collection好,还是使用List或Set好呢?
2 、存放一对值的类型:Map集合
value key
通过key可以找到value
3 、Collection与Map的作用:
Collection主要用于数据输出上
Map主要用于数据查找上
3.2 、List接口
List为Collection的子接口,如果要想使用此接口,则必须通过其子类为其实例化,从运行效果中可以发现,在List中可以有重复的内容。
List接口拥有比Collection接口中更多的方法,主要以下几个常用方法:
在指定位置上加入元素: public void add( int index,Object obj)
返回指定位置的元素: public Object get( int ind)
返回ListIterator实例: public ListIterator < E > listIterator()
3.2 . 1 、常用子类
1 、 ArrayList:是一个新的类,是在JDK 1 .2推出之后才有的。本身属于异步处理。性能高,但是不属于线程的安全处理。只允许使用Iterator接口输出。
2 、Vector:是一个旧的类,是在JDK 1 .0时推出的。本身属于同步处理。性能相对较低,但是属于线程安全的,因为使用了同步。可以使用Iterator或Enumeration(使用类本身)输出
3.2 . 2 、Vector类
Vetor也是经过发展之后不断改良,在最早就已经实现了动态数组的功能,之后之后又增加了List接口的实现,所以在整个代码之中对于Vector本身也有自己的一个特性:
增加元素: public void addElement(Object obj),此功能与add()一样。
枚举输出: public Enumeration < E > elements()
Vector类中还有一个堆栈的类 —— Stack,此类实现了先进后出的功能。
Stack中主要有以下两个方法:
入栈: public Object push(Object item)
出栈: public Object pop()
3.2 . 3 、使用List操作(ArrayList)
例如:以下代码演示了ArrayList的作用
import java.util. * ;
public class ColDemo01 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("A") ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list) ;
}
} ;
例如:使用clear()方法清空里面的全部内容
import java.util. * ;
public class ColDemo02 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("A") ;
// 清空全部的内容
list.clear() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list) ;
}
} ;
例如:测试contains()方法,查找指定内容
import java.util. * ;
public class ColDemo03 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list.contains("A")) ;
System.out.println(list.contains("X")) ;
}
} ;
例如:验证集合是否为空
import java.util. * ;
public class ColDemo04 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
System.out.println(list.isEmpty()) ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list.isEmpty()) ;
}
} ;
例如:以下代码演示了remove()作用
import java.util. * ;
public class ColDemo05 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.remove("B") ;
System.out.println(list) ;
}
} ;
例如:将集合变为对象数组输出
import java.util. * ;
public class ColDemo06 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Object str[] = list.toArray() ;
for(int i=0;i<list.size();i++){
String s = (String)str[i] ;
System.out.println(s) ;
}
}
} ;
之前的所有代码在编译的时候都出现了以下的提示:
注意: ColDemo01.java 使用了未经检查或不安全的操作。
注意: 要了解详细信息,请使用 - Xlint:unchecked 重新编译。
那么这样的错误提示,是因为在JDK 1 .5之后加入了泛型的操作。因为类集中本身是使用Object进行接收的,而且接收的时候牵扯到转型问题,那么如果不指定泛型的话,则里面肯定可以加入各种类型的数据,那么在转型会出现类型转换异常。如下代码所示:
import java.util. * ;
public class ColDemo10 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add(1) ;
list.add('2') ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
if("C".equals(str)){
// 使用了Iterator中的删除语法。
iter.remove() ;
}
}
System.out.println(list) ;
}
} ;
那么此时,就可以加入泛型进行错误的回避,加入之后,集合中只能有一种类型,当然,在实际中集合中的数据也只有一种类型。
import java.util. * ;
public class ColDemo11 {
public static void main(String args[]){
// Collection<String> list = new ArrayList<String>() ;
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add(1) ;
list.add('2') ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
String str = iter.next() ;
System.out.println(str) ;
}
}
} ;
以上加入了泛型操作之后,在编译的时候以上代码就会出现错误提示:
ColDemo11.java: 7 : 找不到符号
符号: 方法 add( int )
位置: 接口 java.util.List < java.lang.String >
list.add( 1 ) ;
^
ColDemo11.java: 8 : 找不到符号
符号: 方法 add( char )
位置: 接口 java.util.List < java.lang.String >
list.add( ' 2 ' ) ;
^
2 错误
所以,此时,代码只能按如下样式编写:
import java.util. * ;
public class ColDemo11 {
public static void main(String args[]){
// Collection<String> list = new ArrayList<String>() ;
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add("B") ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
String str = iter.next() ;
System.out.println(str) ;
}
}
} ;
例如:使用List进行由后向前的输出
import java.util. * ;
public class ColDemo12 {
public static void main(String args[]){
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add("B") ;
list.add(1,"X") ;
list.add(0,"H") ;
list.add(2,"Y") ;
for(int i=list.size()-1;i>=0;i--){
System.out.println(list.get(i)) ;
}
}
} ;
3.2 . 4 、使用List操作(Vector)
例如:使用Vector完成以上的操作
import java.util. * ;
public class ColDemo14 {
public static void main(String args[]){
List<String> list = new Vector<String>() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
Iterator<String> liter = list.iterator() ;
while(liter.hasNext()){
System.out.print(liter.next()+"、") ;
}
}
} ;
可以发现,整个程序与之前没有任何的区别。
3.2 . 5 、使用Stack操作
例如:入栈和出栈
import java.util. * ;
public class ColDemo16 {
public static void main(String args[]){
Stack<String> s = new Stack<String>() ;
s.push("A") ;
s.push("B") ;
s.push("C") ;
System.out.println(s.pop()) ;
System.out.println(s.pop()) ;
System.out.println(s.pop()) ;
System.out.println(s.pop()) ;
}
} ;
如果栈的内容已经空了,再继续出栈的话,则肯定出现以下的错误:
Exception in thread " main " java.util.EmptyStackException
3.3 、Set接口
与List接口不同的是Set接口中本身不能有任何的重复元素。
与List接口不同的是Set接口中并没有对Collection进行扩充,也就是说,Set只是比Collection接口增加了一个不能重复的功能。
JAVA中通过类的HashCode和equals两个方法来确定是否是同一个对象。
3.3 . 1 、常用子类(理解)
1 、HashSet:是散列存放的,无序
2 、TreeSet:是排序的,使用Comparable接口排序(二叉树排序),如果使用Comparable的时候里面的所有字段都要进行比较,否则如果有若干个字段相同,而其他字段没有比较的话,系统会认为是重复的内容,而去掉。
二叉树(Binary Tree),三种遍历方式:
前序遍历:根 - 左 - 右
中序遍历:左 - 根 - 右
后序遍历:左 - 右 - 根
3.3 . 2 、使用Set操作(HashSet)
例如:观察HashSet使用
import java.util. * ;
public class ColDemo17 {
public static void main(String args[]){
Set<String> list = new HashSet<String>() ;
list.add("A") ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3.3 . 3 、使用Set操作(TreeSet)
例如:观察TreeSet功能
import java.util. * ;
public class ColDemo18 {
public static void main(String args[]){
Set<String> list = new TreeSet<String>() ;
list.add("A") ;
list.add("X") ;
list.add("B") ;
list.add("D") ;
list.add("Q") ;
list.add("Q") ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
那么,如果现在给定了一个类的若干对象,如果使用TreeSet存放是否可以?
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名;" + this.name + ",年龄;" + this.age ;
}
} ;
public class ColDemo19 {
public static void main(String args[]){
Set<Person> list = new TreeSet<Person>() ;
list.add(new Person("张三",30)) ;
list.add(new Person("李四",31)) ;
list.add(new Person("王五",32)) ;
Iterator<Person> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
以上代码运行的时候出现了以下的错误:
Exception in thread " main " java.lang.ClassCastException: Person
类型转换异常,因为TreeSet本身是带排序功能的,如果现在要对一个对象进行排序,则必须指定对象的排序规则,排序规则通过比较器 —— Comparable完成。
import java.util. * ;
class Person implements Comparable < Person > {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名;" + this.name + ",年龄;" + this.age ;
}
public int compareTo(Person per){
if(this.age>per.age){
return -1 ;
}else if(this.age<per.age){
return 1 ;
}else{
return 0 ;
}
}
} ;
public class ColDemo20 {
public static void main(String args[]){
Set<Person> list = new TreeSet<Person>() ;
list.add(new Person("张三",30)) ;
list.add(new Person("李四",31)) ;
list.add(new Person("王五",32)) ;
Iterator<Person> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
观察TreeSet的问题:
题目:设计一个学生类,此类包含姓名、年龄、成绩,产生一个对象数组,要求按成绩由高到低排序、如果成绩相等,则按年龄由低到高排序。
通过java.util.Arrays类可以排序。 public static void sort(Object[] a)
发现以上的操作可以对一个对象数组进行排序
import java.util. * ;
class Student implements Comparable < Student > {
private String name ;
private int age ;
private float score ;
public Student(String name,int age,float score){
this.name = name ;
this.age = age ;
this.score = score ;
}
public String toString(){
return name + "\t\t" + age + "\t\t" + score ;
}
public int compareTo(Student stu){
if(this.score>stu.score){
return -1 ;
}else if(this.score<stu.score){
return 1 ;
}else{
if(this.age>stu.age){
return 1 ;
}else if(this.age<stu.age){
return -1 ;
}else{
return this.name.compareTo(stu.name) ;
}
}
}
} ;
public class ColDemo34 {
public static void main(String args[]){
Set<Student> s = new TreeSet<Student>() ;
s.add(new Student("张三",20,90.0f)) ;
s.add(new Student("李四",22,90.0f)) ;
s.add(new Student("王五",20,99.0f)) ;
s.add(new Student("赵六",20,70.0f)) ;
s.add(new Student("孙七",22,100.0f)) ;
s.add(new Student("赵九",22,100.0f)) ;
Iterator<Student> iter = s.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3.3 . 4 、二叉树排序(理解)
对于整个JAVA来说所有的排序操作都是以Comparable展开的,所以现在重点观察Comparable。
以下代码全部使用String为例。
例如:使用Comparable接收String对象
public class ColDemo22 {
public static void main(String args[]){
Comparable c = "abc" ;
System.out.println(c) ;
}
} ;
分析:
1 、所有对象打印的时候调用的都是toString()
2 、String类中已经覆写toString()
3 、String是Object的子类。
4 、如果直接打印Comparable接口对象,调用的是toString()方法,但是此时此对象是通过String实例化的,所以肯定使的是String中已经被覆写toString()方法。
对于JAVA中可以使用以下的方式规定出二叉树的排序方式:
class BinaryTree {
class Node{
// 具体的内容
private Comparable data ;
// 保存左子树
private Node left ;
// 保存右子树
private Node right ;
public void addNode(Node newNode){
// 要确定是放在左子树还是右子树
if(newNode.data.compareTo(this.data)<0){
// 放在左子树
if(this.left==null){
this.left = newNode ;
}else{
this.left.addNode(newNode) ;
}
}
if(newNode.data.compareTo(this.data)>0){
// 放在左子树
if(this.right==null){
this.right = newNode ;
}else{
this.right.addNode(newNode) ;
}
}
}
public void printNode(){
// 先输出左子树
if(this.left!=null){
this.left.printNode() ;
}
// 输出根节点
System.out.println(this.data) ;
// 输出右子树
if(this.right!=null){
this.right.printNode() ;
}
}
};
// 确定根元素
private Node root ;
public void add(Comparable data){
Node newNode = new Node() ;
newNode.data = data ;
if(root==null){
// 第一个元素,设置成根元素
root = newNode ;
}else{
// 如果此语句没有执行的话,则必须确定好是放在左子树还是右子树
root.addNode(newNode) ;
}
}
public void print(){
this.root.printNode() ;
}
} ;
public class ColDemo23 {
public static void main(String args[]){
BinaryTree bt = new BinaryTree() ;
bt.add("C") ;
bt.add("X") ;
bt.add("A") ;
bt.add("S") ;
bt.add("O") ;
bt.print() ;
}
} ;
3.4 、Iterator接口
3.4 . 1 、接口的主要用处
Iterator是一个迭代输出接口。
Iterator接口定义:
判断下一个元素是否有内容: public boolean hasNext()
取出内容: public Object next() ;
从集合中删除元素: public void remove() ;
例如:使用Iterator输出Collection(List)中的内容
import java.util. * ;
public class ColDemo07 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
System.out.println(str) ;
}
}
} ;
3.4 . 2 、删除元素的说明
在List和Iterator上都有remove方法。
在使用Iterator迭代输出的时候,不能修改List中的内容,如果一旦修改,则肯定会出现错误。
例如:以下代码在迭代输出的时候使用了List中的remove方法。
import java.util. * ;
public class ColDemo08 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
if("C".equals(str)){
// 使用了List中的删除语法。
list.remove(str) ;
}
}
}
} ;
以上代码运行时出现了错误:
Exception in thread " main " java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at ColDemo08.main(ColDemo08.java: 11 )
同样的代码,现在直接使用Iterator中的删除方法完成:
import java.util. * ;
public class ColDemo09 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
if("C".equals(str)){
// 使用了Iterator中的删除语法。
iter.remove() ;
}
}
System.out.println(list) ;
}
} ;
3.4 . 3 、子接口 —— ListIterator
Iterator本身只支持由前向后的输出,并不支持由后向前,那么其有一个子接口 —— ListIterator,此接口可以将内容从前向后,也可以从后向前,但是必须注意的是:必须先由前向后输出完之后,才能由后向前输出。只有List接口的对象才可以使用此种方法。
ListIterator中的主要方法:
判断是否有下一个内容: public boolean hasNext()
取出下一个元素: public Object next()
判断是否有上一个元素: public boolean hasPrevious();
取出上一个元素: public Object previous() ;
本身ListIterator也是支持泛型的
例如:以下代码演示了ListIterator的作用
import java.util. * ;
public class ColDemo13 {
public static void main(String args[]){
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
ListIterator<String> liter = list.listIterator() ;
System.out.println(" ============== 由前向后输出 ==================") ;
while(liter.hasNext()){
System.out.print(liter.next()+"、") ;
}
System.out.println("") ;
System.out.println(" ============== 由后向前输出 ==================") ;
while(liter.hasPrevious()){
System.out.print(liter.previous()+"、") ;
}
}
} ;
3.4 、Enumeration接口
是最早的迭代输出接口,其本身的功能和Iterator类似,但是因为其出现较早,而且代码本身存在安全问题,所以现在使用较少,但是对于一些原有的系统中的若干方法,还是只能使用Enumeration输出。
Enumerationi接口的定义:
判断是否有下一个元素: public boolean hasMoreElements()
取出元素: public Object nextElement()
例如:使用Enumeration输出Vector中的内容
import java.util. * ;
public class ColDemo15 {
public static void main(String args[]){
Vector<String> list = new Vector<String>() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
Enumeration<String> enu = list.elements() ;
while(enu.hasMoreElements()){
System.out.print(enu.nextElement()+"、") ;
}
}
} ;
3.5 、foreach输出(了解)
提供了比Iterator更简单的输出语法,但是是在JDK 1 .5之后才增加的。
语法格式:
for (类型 对象:集合) {
进行对象的操作
}
例如:验证foreach语法
import java.util. * ;
class Person implements Comparable < Person > {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名;" + this.name + ",年龄;" + this.age ;
}
public int compareTo(Person per){
if(this.age>per.age){
return -1 ;
}else if(this.age<per.age){
return 1 ;
}else{
return 0 ;
}
}
} ;
public class ColDemo21 {
public static void main(String args[]){
Set<Person> list = new TreeSet<Person>() ;
list.add(new Person("张三",30)) ;
list.add(new Person("李四",31)) ;
list.add(new Person("王五",32)) ;
for(Person p:list){
System.out.println(p) ;
}
}
} ;
3.6 、Map接口
与之前Collection不同的是Map接口可以存放一对值。
Map与Set一样,本身不能有任何重复的内容(key不能重复)。
主要操作方法如下;
向集合中插入一组数据: public V put(K key,V value)
根据key取出value: public V get(Object key)
在Map中因为其组成较为特殊,所以本身不直接支持Iterator输出。
Set实例 entrySet() 步骤:Map 区分key和value。 Map.Entry实例 Iterator
Map.Entry:是Map的内部接口
|- 得到key: public K getKey()
|- 得到value: public V getValue()
操作方法:
|- 将全部的Map变为Set集合: public Set < Map.Entry < K,V >> entrySet()
|- 将全部的key变为Set集合: public Set < K > keySet()
|- 将全部的value变为Collection集合: public Collection < V > values()
3.6 . 1 、常用子类
1 、HashMap:是一个新的类,是在JDK 1 .2之后推出的,属于异步处理方式。
2 、Hashtable:是一个旧的类,是在JDK 1 .0时推出,属于同步处理方式
3 、TreeMap:按照key排序,同样key所在的类必须实现Comparable接口
3.6 . 2 、Hashtable子类 —— Properties
与Hashtable不同的是Properties主要操作的内容为字符串,表示的是属性操作。
Properties的主要方法:
设置属性: public Object setProperty(String key, String value)
取得属性:
|- public String getProperty(String key):根据key找到value,没找到返回null。
|- public String getProperty(String key,String defaultValue):如果没有找到,则指定默认值。
保存属性到文件: public void store(OutputStream out,String comments) throws IOException
从文件中读取内容: public void load(InputStream inStream) throws IOException
把文件保存成XML样式:
|- public void storeToXML(OutputStream os,String comment) throws IOException
从XML样式的文件之中读取属性:
|- public void loadFromXML(InputStream in) throws IOException,
InvalidPropertiesFormatException
3.6 . 3 、Map操作(HashMap)
例如:通过HashMap验证Map的使用
import java.util. * ;
public class ColDemo24 {
public static void main(String arg[]){
Map<String,String> m = new HashMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
String str = m.get("zhangsan") ;
System.out.println(str) ;
System.out.println(m.get("xxx")) ;
}
} ;
3.6 . 4 、Map操作(Hashtable)
import java.util. * ;
public class ColDemo25 {
public static void main(String arg[]){
Map<String,String> m = new Hashtable<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
String str = m.get("zhangsan") ;
System.out.println(str) ;
System.out.println(m.get("xxx")) ;
}
} ;
3.6 . 5 、Map操作(TreeMap)
import java.util. * ;
public class ColDemo26 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
String str = m.get("zhangsan") ;
System.out.println(str) ;
System.out.println(m.get("xxx")) ;
}
} ;
3.6 . 6 、Map操作(输出)
1 、使用Iterator输出Map中的全部数据(格式是固定的)
public Set < Map.Entry < K,V >> entrySet()
import java.util. * ;
public class ColDemo27 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
Set<Map.Entry<String,String>> list = m.entrySet() ;
Iterator<Map.Entry<String,String>> iter = list.iterator() ;
while(iter.hasNext()){
Map.Entry me = iter.next() ;
System.out.println(me.getKey() + " --> " + me.getValue()) ;
}
}
} ;
2 、将Map中全部的key输出
import java.util. * ;
public class ColDemo28 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
Set<String> list = m.keySet() ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3 、将Map中全部的value输出
import java.util. * ;
public class ColDemo29 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
Collection<String> list = m.values() ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3.6 . 7 、Map操作(问题)
例如:定义一个Person类,里面有name和age属性,之后在Map中保存一个person对象。
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
} ;
public class ColDemo30 {
public static void main(String args[]){
Map<String,Person> m = new HashMap<String,Person>() ;
m.put("zhangsan",new Person("张三",30)) ;
System.out.println(m.get("zhangsan")) ;
}
} ;
以上的运行结果,可以发现内容已经查找出来了。如果现在换个方式,使用Person对象表示张三呢?
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
} ;
public class ColDemo31 {
public static void main(String args[]){
Map<Person,String> m = new HashMap<Person,String>() ;
m.put(new Person("张三",30),"zhangsan") ;
System.out.println(m.get(new Person("张三",30))) ;
}
} ;
从运行结果,发现,里面没有任何的内容,返回一个“ null ”。此时再修改代码:
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
} ;
public class ColDemo32 {
public static void main(String args[]){
Map<Person,String> m = new HashMap<Person,String>() ;
Person p = new Person("张三",30) ;
m.put(p,"zhangsan") ;
System.out.println(m.get(p)) ;
}
} ;
以上可以找到代号。
从以上代码中可以发现问题:
如果使用字符串作为key,就算是匿名对象也是可以找得到
如果自己编写了一个key,则如果使用匿名对象则无法找到。
因为在对象上有一个对象自己的编码,那么如果要想使用此编码,则必须在对象所在的类中覆写Object类中的hashCode()方法。
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
public boolean equals(Object obj){
if(this==obj){
return true ;
}
if(!(obj instanceof Person)){
return false ;
}
Person p = (Person)obj ;
if(this.name.equals(p.name)&&this.age==p.age){
return true ;
}else{
return false ;
}
}
public int hashCode(){
// 正常来说,应该为hashCode的产生自己定义一个公式
return this.age * this.name.hashCode() ;
}
} ;
public class ColDemo33 {
public static void main(String args[]){
Map<Person,String> m = new HashMap<Person,String>() ;
m.put(new Person("张三",30),"zhangsan") ;
System.out.println(m.get(new Person("张三",30))) ;
}
} ;
3.6 . 8 、Properties操作
1 、向Properties中设置属性,并取得属性
import java.util. * ;
public class ColDemo35 {
public static void main(String args[]){
Properties pro = new Properties() ;
pro.setProperty("BJ","BeiJing") ;
pro.setProperty("NJ","NanJing") ;
pro.setProperty("SH","ShangHai") ;
System.out.println(pro.getProperty("BJ")) ;
System.out.println(pro.getProperty("XJ")) ;
System.out.println(pro.getProperty("XJ","nofound")) ;
}
} ;
2 、将全部的属性保存在普通文件之中
import java.util. * ;
import java.io. * ;
public class ColDemo36 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.setProperty("BJ","BeiJing") ;
pro.setProperty("NJ","NanJing") ;
pro.setProperty("SH","ShangHai") ;
pro.store(new FileOutputStream(new File("e:\\pro.ini")),"AREA") ;
}
} ;
3 、从文件中读取属性
import java.util. * ;
import java.io. * ;
public class ColDemo37 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.load(new FileInputStream(new File("e:\\pro.ini"))) ;
System.out.println(pro.getProperty("BJ")) ;
}
} ;
4 、将属性按照XML样式的风格进行保存
import java.util. * ;
import java.io. * ;
public class ColDemo38 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.setProperty("BJ","BeiJing") ;
pro.setProperty("NJ","NanJing") ;
pro.setProperty("SH","ShangHai") ;
pro.storeToXML(new FileOutputStream(new File("e:\\pro.xml")),"AREA") ;
}
} ;
5 、将属性从XML中读取出来
import java.util. * ;
import java.io. * ;
public class ColDemo39 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.loadFromXML(new FileInputStream(new File("e:\\pro.xml"))) ;
System.out.println(pro.getProperty("BJ")) ;
}
} ;
现在操作属性的时候基本上都是以XML样式为准。
3.7 、实例
3.7 . 1 、实例一
一个人有多本书,一本书属于一个人。
package org.lxh.demo1;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
class Person {
private String name;
private int age;
private List<Book> listBooks;
public Person() {
this.listBooks = new ArrayList<Book>();
}
public Person(String name, int age) {
this();
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;
}
public List<Book> getlistBooks() {
return listBooks;
}
public void setlistBooks(List<Book> listBooks) {
this.listBooks = listBooks;
}
}
class Book {
private String title;
private Person person;
public Book(String title) {
super();
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
public class Demo01 {
public static void main(String[] args) {
Person per = new Person("张三", 30);
Book b1 = new Book("JAVA");
Book b2 = new Book("C");
Book b3 = new Book("NET");
per.getlistBooks().add(b1);
per.getlistBooks().add(b2);
per.getlistBooks().add(b3);
b1.setPerson(per);
b2.setPerson(per);
b3.setPerson(per);
System.out.println("姓名:" + per.getName() + ",年龄:" + per.getAge());
Iterator<Book> iter = per.getlistBooks().iterator();
while (iter.hasNext()) {
System.out.println("\t|- " + iter.next().getTitle());
}
}
}
3.7 . 2 、实例二
一个学生可以选多个课程,一个课程可以多个学生参加。
package org.lxh.demo2;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
class Student {
private String name;
private List<Course> listCourses;
public Student() {
this.listCourses = new ArrayList<Course>();
}
public Student(String name) {
this();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getlistCourses() {
return listCourses;
}
public void setlistCourses(List<Course> listCourses) {
this.listCourses = listCourses;
}
}
class Course {
private String name;
public List<Student> listStudents;
public Course() {
this.listStudents = new ArrayList<Student>();
}
public Course(String name) {
this();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getlistStudents() {
return listStudents;
}
public void setlistStudents(List<Student> listStudents) {
this.listStudents = listStudents;
}
}
public class Demo02 {
public static void main(String[] args) {
Student s1 = new Student("张三");
Student s2 = new Student("李四");
Student s3 = new Student("王五");
Student s4 = new Student("赵六");
Student s5 = new Student("孙七");
Course c1 = new Course("JAVA");
Course c2 = new Course("Oracle");
// 设置关系
s1.getlistCourses().add(c1);
c1.getlistStudents().add(s1);
s2.getlistCourses().add(c1);
c1.getlistStudents().add(s2);
s3.getlistCourses().add(c1);
c1.getlistStudents().add(s3);
s4.getlistCourses().add(c2);
c2.getlistStudents().add(s4);
s5.getlistCourses().add(c2);
c2.getlistStudents().add(s5);
s1.getlistCourses().add(c2);
c2.getlistStudents().add(s1);
s2.getlistCourses().add(c2);
c2.getlistStudents().add(s2);
System.out.println("学生:" + s1.getName());
Iterator<Course> iter1 = s1.getlistCourses().iterator();
while (iter1.hasNext()) {
System.out.println("\t|- " + iter1.next().getName());
}
System.out.println("---------------------------------");
System.out.println("课程:" + c2.getName());
Iterator<Student> iter2 = c2.getlistStudents().iterator();
while (iter2.hasNext()) {
System.out.println("\t|- " + iter2.next().getName());
}
}
}
4 、总结
1 、Collection(保存单个对象)
List:允许有重复元素,拥有更多的操作方法
|- ArrayList:新的、异步处理
|- Vector:旧的, 同步处理,支持Iterator和Enumeration两种输出
|- Stack:入栈、出栈
Set:不允许有重复元素,靠hashCode和equals方法来区分重复元素
|- HashSet:无序
|- TreeSet:有序、按照Comparable指定的规则排序
常用方法:add()、iterator()、remove
2 、Map(保存一对对象)
HashMap:新的类,异步处理
Hashtable:旧的类,同步处理
|- Properties(属性操作),可以将属性保存在文件之中
TreeMap:排序操作类,此类按key排序,使用Comparable完成
主要方法:put、get、entrySet
Map不能直接使用Iterator输出,必须转换成Set,通过Map.Entry分离key和value
3 、Iterator
输出接口,只要是类集都使用此接口输出,一般情况下很少有删除代码出现
主要方法:
|- 判断是否有下一个元素: public boolean hasNext()
|- 取出当前元素: public Object next()
子接口:ListIterator
|- 双向输出,但是此接口只能通过List实例化
4 、Enumeration接口
最早的输出接口,现在部分代码上依然使用
1 、课程名称:JAVA类集
类集的作用、Collection、Map、Iterator、ListIterator、List、Set、Enumeration、二叉树算法
JAVA SE的最重要四块知识:面向对象、类集、JAVA IO、数据库编程
2 、知识点
2.1 、上次课程的主要知识点
1 、IO操作
BufferedReader:一次性读取数据
PrintStream:打印流
字节流:InputStream、OutputStream
File类
2 、对象序列化
2.2 、本次预计讲解的知识点
1 、类集的作用
2 、单值集合:Collection、List、Set
3 、二元偶集合:Map
4 、输出:Iterator、ListIterator、Enumeration
5 、类集的作用
3 、具体内容
3.1 、类集的作用
类集:就是一个动态的对象数组。
对象数组:可以保存一组对象,但是其本身有长度的限制。
类集可以保存一组对象,但是此保存没有长度的限制。
在JAVA中类集的操作都在java.util包中,本身也分为两种操作形式:
1 、存放单值的类集,最大的接口是Collection,每次可以存放一个值。但是其下又分为两个子接口:
List接口:表示可以重复,插入的顺序即为输出顺序
Set接口:不能够有重复元素
List接口在实际中应用较为广泛
主要操作方法:
添加一个对象: public boolean add(Object obj)
清空里面的所有内容: public void clear() ;
测试集合中是否包含指定元素: boolean contains(Object o)
判断集合是否为空: public boolean isEmpty()
从集合中删除指定内容: public boolean remove(Object o)
取得集合中大小: public int size()
将集合变为对象数组: public Object[] toArray()
将集合变为Iterator实例: public Iterator < E > iterator()
对于整个Collection集合,只允许从前向后输出,没有从后向前输出的功能。
讨论:
是使用Collection好,还是使用List或Set好呢?
2 、存放一对值的类型:Map集合
value key
通过key可以找到value
3 、Collection与Map的作用:
Collection主要用于数据输出上
Map主要用于数据查找上
3.2 、List接口
List为Collection的子接口,如果要想使用此接口,则必须通过其子类为其实例化,从运行效果中可以发现,在List中可以有重复的内容。
List接口拥有比Collection接口中更多的方法,主要以下几个常用方法:
在指定位置上加入元素: public void add( int index,Object obj)
返回指定位置的元素: public Object get( int ind)
返回ListIterator实例: public ListIterator < E > listIterator()
3.2 . 1 、常用子类
1 、 ArrayList:是一个新的类,是在JDK 1 .2推出之后才有的。本身属于异步处理。性能高,但是不属于线程的安全处理。只允许使用Iterator接口输出。
2 、Vector:是一个旧的类,是在JDK 1 .0时推出的。本身属于同步处理。性能相对较低,但是属于线程安全的,因为使用了同步。可以使用Iterator或Enumeration(使用类本身)输出
3.2 . 2 、Vector类
Vetor也是经过发展之后不断改良,在最早就已经实现了动态数组的功能,之后之后又增加了List接口的实现,所以在整个代码之中对于Vector本身也有自己的一个特性:
增加元素: public void addElement(Object obj),此功能与add()一样。
枚举输出: public Enumeration < E > elements()
Vector类中还有一个堆栈的类 —— Stack,此类实现了先进后出的功能。
Stack中主要有以下两个方法:
入栈: public Object push(Object item)
出栈: public Object pop()
3.2 . 3 、使用List操作(ArrayList)
例如:以下代码演示了ArrayList的作用
import java.util. * ;
public class ColDemo01 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("A") ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list) ;
}
} ;
例如:使用clear()方法清空里面的全部内容
import java.util. * ;
public class ColDemo02 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("A") ;
// 清空全部的内容
list.clear() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list) ;
}
} ;
例如:测试contains()方法,查找指定内容
import java.util. * ;
public class ColDemo03 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list.contains("A")) ;
System.out.println(list.contains("X")) ;
}
} ;
例如:验证集合是否为空
import java.util. * ;
public class ColDemo04 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
System.out.println(list.isEmpty()) ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
System.out.println(list.isEmpty()) ;
}
} ;
例如:以下代码演示了remove()作用
import java.util. * ;
public class ColDemo05 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.remove("B") ;
System.out.println(list) ;
}
} ;
例如:将集合变为对象数组输出
import java.util. * ;
public class ColDemo06 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Object str[] = list.toArray() ;
for(int i=0;i<list.size();i++){
String s = (String)str[i] ;
System.out.println(s) ;
}
}
} ;
之前的所有代码在编译的时候都出现了以下的提示:
注意: ColDemo01.java 使用了未经检查或不安全的操作。
注意: 要了解详细信息,请使用 - Xlint:unchecked 重新编译。
那么这样的错误提示,是因为在JDK 1 .5之后加入了泛型的操作。因为类集中本身是使用Object进行接收的,而且接收的时候牵扯到转型问题,那么如果不指定泛型的话,则里面肯定可以加入各种类型的数据,那么在转型会出现类型转换异常。如下代码所示:
import java.util. * ;
public class ColDemo10 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add(1) ;
list.add('2') ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
if("C".equals(str)){
// 使用了Iterator中的删除语法。
iter.remove() ;
}
}
System.out.println(list) ;
}
} ;
那么此时,就可以加入泛型进行错误的回避,加入之后,集合中只能有一种类型,当然,在实际中集合中的数据也只有一种类型。
import java.util. * ;
public class ColDemo11 {
public static void main(String args[]){
// Collection<String> list = new ArrayList<String>() ;
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add(1) ;
list.add('2') ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
String str = iter.next() ;
System.out.println(str) ;
}
}
} ;
以上加入了泛型操作之后,在编译的时候以上代码就会出现错误提示:
ColDemo11.java: 7 : 找不到符号
符号: 方法 add( int )
位置: 接口 java.util.List < java.lang.String >
list.add( 1 ) ;
^
ColDemo11.java: 8 : 找不到符号
符号: 方法 add( char )
位置: 接口 java.util.List < java.lang.String >
list.add( ' 2 ' ) ;
^
2 错误
所以,此时,代码只能按如下样式编写:
import java.util. * ;
public class ColDemo11 {
public static void main(String args[]){
// Collection<String> list = new ArrayList<String>() ;
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add("B") ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
String str = iter.next() ;
System.out.println(str) ;
}
}
} ;
例如:使用List进行由后向前的输出
import java.util. * ;
public class ColDemo12 {
public static void main(String args[]){
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add("B") ;
list.add(1,"X") ;
list.add(0,"H") ;
list.add(2,"Y") ;
for(int i=list.size()-1;i>=0;i--){
System.out.println(list.get(i)) ;
}
}
} ;
3.2 . 4 、使用List操作(Vector)
例如:使用Vector完成以上的操作
import java.util. * ;
public class ColDemo14 {
public static void main(String args[]){
List<String> list = new Vector<String>() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
Iterator<String> liter = list.iterator() ;
while(liter.hasNext()){
System.out.print(liter.next()+"、") ;
}
}
} ;
可以发现,整个程序与之前没有任何的区别。
3.2 . 5 、使用Stack操作
例如:入栈和出栈
import java.util. * ;
public class ColDemo16 {
public static void main(String args[]){
Stack<String> s = new Stack<String>() ;
s.push("A") ;
s.push("B") ;
s.push("C") ;
System.out.println(s.pop()) ;
System.out.println(s.pop()) ;
System.out.println(s.pop()) ;
System.out.println(s.pop()) ;
}
} ;
如果栈的内容已经空了,再继续出栈的话,则肯定出现以下的错误:
Exception in thread " main " java.util.EmptyStackException
3.3 、Set接口
与List接口不同的是Set接口中本身不能有任何的重复元素。
与List接口不同的是Set接口中并没有对Collection进行扩充,也就是说,Set只是比Collection接口增加了一个不能重复的功能。
JAVA中通过类的HashCode和equals两个方法来确定是否是同一个对象。
3.3 . 1 、常用子类(理解)
1 、HashSet:是散列存放的,无序
2 、TreeSet:是排序的,使用Comparable接口排序(二叉树排序),如果使用Comparable的时候里面的所有字段都要进行比较,否则如果有若干个字段相同,而其他字段没有比较的话,系统会认为是重复的内容,而去掉。
二叉树(Binary Tree),三种遍历方式:
前序遍历:根 - 左 - 右
中序遍历:左 - 根 - 右
后序遍历:左 - 右 - 根
3.3 . 2 、使用Set操作(HashSet)
例如:观察HashSet使用
import java.util. * ;
public class ColDemo17 {
public static void main(String args[]){
Set<String> list = new HashSet<String>() ;
list.add("A") ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3.3 . 3 、使用Set操作(TreeSet)
例如:观察TreeSet功能
import java.util. * ;
public class ColDemo18 {
public static void main(String args[]){
Set<String> list = new TreeSet<String>() ;
list.add("A") ;
list.add("X") ;
list.add("B") ;
list.add("D") ;
list.add("Q") ;
list.add("Q") ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
那么,如果现在给定了一个类的若干对象,如果使用TreeSet存放是否可以?
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名;" + this.name + ",年龄;" + this.age ;
}
} ;
public class ColDemo19 {
public static void main(String args[]){
Set<Person> list = new TreeSet<Person>() ;
list.add(new Person("张三",30)) ;
list.add(new Person("李四",31)) ;
list.add(new Person("王五",32)) ;
Iterator<Person> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
以上代码运行的时候出现了以下的错误:
Exception in thread " main " java.lang.ClassCastException: Person
类型转换异常,因为TreeSet本身是带排序功能的,如果现在要对一个对象进行排序,则必须指定对象的排序规则,排序规则通过比较器 —— Comparable完成。
import java.util. * ;
class Person implements Comparable < Person > {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名;" + this.name + ",年龄;" + this.age ;
}
public int compareTo(Person per){
if(this.age>per.age){
return -1 ;
}else if(this.age<per.age){
return 1 ;
}else{
return 0 ;
}
}
} ;
public class ColDemo20 {
public static void main(String args[]){
Set<Person> list = new TreeSet<Person>() ;
list.add(new Person("张三",30)) ;
list.add(new Person("李四",31)) ;
list.add(new Person("王五",32)) ;
Iterator<Person> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
观察TreeSet的问题:
题目:设计一个学生类,此类包含姓名、年龄、成绩,产生一个对象数组,要求按成绩由高到低排序、如果成绩相等,则按年龄由低到高排序。
通过java.util.Arrays类可以排序。 public static void sort(Object[] a)
发现以上的操作可以对一个对象数组进行排序
import java.util. * ;
class Student implements Comparable < Student > {
private String name ;
private int age ;
private float score ;
public Student(String name,int age,float score){
this.name = name ;
this.age = age ;
this.score = score ;
}
public String toString(){
return name + "\t\t" + age + "\t\t" + score ;
}
public int compareTo(Student stu){
if(this.score>stu.score){
return -1 ;
}else if(this.score<stu.score){
return 1 ;
}else{
if(this.age>stu.age){
return 1 ;
}else if(this.age<stu.age){
return -1 ;
}else{
return this.name.compareTo(stu.name) ;
}
}
}
} ;
public class ColDemo34 {
public static void main(String args[]){
Set<Student> s = new TreeSet<Student>() ;
s.add(new Student("张三",20,90.0f)) ;
s.add(new Student("李四",22,90.0f)) ;
s.add(new Student("王五",20,99.0f)) ;
s.add(new Student("赵六",20,70.0f)) ;
s.add(new Student("孙七",22,100.0f)) ;
s.add(new Student("赵九",22,100.0f)) ;
Iterator<Student> iter = s.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3.3 . 4 、二叉树排序(理解)
对于整个JAVA来说所有的排序操作都是以Comparable展开的,所以现在重点观察Comparable。
以下代码全部使用String为例。
例如:使用Comparable接收String对象
public class ColDemo22 {
public static void main(String args[]){
Comparable c = "abc" ;
System.out.println(c) ;
}
} ;
分析:
1 、所有对象打印的时候调用的都是toString()
2 、String类中已经覆写toString()
3 、String是Object的子类。
4 、如果直接打印Comparable接口对象,调用的是toString()方法,但是此时此对象是通过String实例化的,所以肯定使的是String中已经被覆写toString()方法。
对于JAVA中可以使用以下的方式规定出二叉树的排序方式:
class BinaryTree {
class Node{
// 具体的内容
private Comparable data ;
// 保存左子树
private Node left ;
// 保存右子树
private Node right ;
public void addNode(Node newNode){
// 要确定是放在左子树还是右子树
if(newNode.data.compareTo(this.data)<0){
// 放在左子树
if(this.left==null){
this.left = newNode ;
}else{
this.left.addNode(newNode) ;
}
}
if(newNode.data.compareTo(this.data)>0){
// 放在左子树
if(this.right==null){
this.right = newNode ;
}else{
this.right.addNode(newNode) ;
}
}
}
public void printNode(){
// 先输出左子树
if(this.left!=null){
this.left.printNode() ;
}
// 输出根节点
System.out.println(this.data) ;
// 输出右子树
if(this.right!=null){
this.right.printNode() ;
}
}
};
// 确定根元素
private Node root ;
public void add(Comparable data){
Node newNode = new Node() ;
newNode.data = data ;
if(root==null){
// 第一个元素,设置成根元素
root = newNode ;
}else{
// 如果此语句没有执行的话,则必须确定好是放在左子树还是右子树
root.addNode(newNode) ;
}
}
public void print(){
this.root.printNode() ;
}
} ;
public class ColDemo23 {
public static void main(String args[]){
BinaryTree bt = new BinaryTree() ;
bt.add("C") ;
bt.add("X") ;
bt.add("A") ;
bt.add("S") ;
bt.add("O") ;
bt.print() ;
}
} ;
3.4 、Iterator接口
3.4 . 1 、接口的主要用处
Iterator是一个迭代输出接口。
Iterator接口定义:
判断下一个元素是否有内容: public boolean hasNext()
取出内容: public Object next() ;
从集合中删除元素: public void remove() ;
例如:使用Iterator输出Collection(List)中的内容
import java.util. * ;
public class ColDemo07 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
System.out.println(str) ;
}
}
} ;
3.4 . 2 、删除元素的说明
在List和Iterator上都有remove方法。
在使用Iterator迭代输出的时候,不能修改List中的内容,如果一旦修改,则肯定会出现错误。
例如:以下代码在迭代输出的时候使用了List中的remove方法。
import java.util. * ;
public class ColDemo08 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
if("C".equals(str)){
// 使用了List中的删除语法。
list.remove(str) ;
}
}
}
} ;
以上代码运行时出现了错误:
Exception in thread " main " java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at ColDemo08.main(ColDemo08.java: 11 )
同样的代码,现在直接使用Iterator中的删除方法完成:
import java.util. * ;
public class ColDemo09 {
public static void main(String args[]){
// Collection list = new ArrayList() ;
List list = new ArrayList() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
Iterator iter = list.iterator() ;
while(iter.hasNext()){
String str = (String)iter.next() ;
if("C".equals(str)){
// 使用了Iterator中的删除语法。
iter.remove() ;
}
}
System.out.println(list) ;
}
} ;
3.4 . 3 、子接口 —— ListIterator
Iterator本身只支持由前向后的输出,并不支持由后向前,那么其有一个子接口 —— ListIterator,此接口可以将内容从前向后,也可以从后向前,但是必须注意的是:必须先由前向后输出完之后,才能由后向前输出。只有List接口的对象才可以使用此种方法。
ListIterator中的主要方法:
判断是否有下一个内容: public boolean hasNext()
取出下一个元素: public Object next()
判断是否有上一个元素: public boolean hasPrevious();
取出上一个元素: public Object previous() ;
本身ListIterator也是支持泛型的
例如:以下代码演示了ListIterator的作用
import java.util. * ;
public class ColDemo13 {
public static void main(String args[]){
List<String> list = new ArrayList<String>() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
ListIterator<String> liter = list.listIterator() ;
System.out.println(" ============== 由前向后输出 ==================") ;
while(liter.hasNext()){
System.out.print(liter.next()+"、") ;
}
System.out.println("") ;
System.out.println(" ============== 由后向前输出 ==================") ;
while(liter.hasPrevious()){
System.out.print(liter.previous()+"、") ;
}
}
} ;
3.4 、Enumeration接口
是最早的迭代输出接口,其本身的功能和Iterator类似,但是因为其出现较早,而且代码本身存在安全问题,所以现在使用较少,但是对于一些原有的系统中的若干方法,还是只能使用Enumeration输出。
Enumerationi接口的定义:
判断是否有下一个元素: public boolean hasMoreElements()
取出元素: public Object nextElement()
例如:使用Enumeration输出Vector中的内容
import java.util. * ;
public class ColDemo15 {
public static void main(String args[]){
Vector<String> list = new Vector<String>() ;
list.add("A") ;
list.add("B") ;
list.add("C") ;
list.add("D") ;
list.add("E") ;
Enumeration<String> enu = list.elements() ;
while(enu.hasMoreElements()){
System.out.print(enu.nextElement()+"、") ;
}
}
} ;
3.5 、foreach输出(了解)
提供了比Iterator更简单的输出语法,但是是在JDK 1 .5之后才增加的。
语法格式:
for (类型 对象:集合) {
进行对象的操作
}
例如:验证foreach语法
import java.util. * ;
class Person implements Comparable < Person > {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名;" + this.name + ",年龄;" + this.age ;
}
public int compareTo(Person per){
if(this.age>per.age){
return -1 ;
}else if(this.age<per.age){
return 1 ;
}else{
return 0 ;
}
}
} ;
public class ColDemo21 {
public static void main(String args[]){
Set<Person> list = new TreeSet<Person>() ;
list.add(new Person("张三",30)) ;
list.add(new Person("李四",31)) ;
list.add(new Person("王五",32)) ;
for(Person p:list){
System.out.println(p) ;
}
}
} ;
3.6 、Map接口
与之前Collection不同的是Map接口可以存放一对值。
Map与Set一样,本身不能有任何重复的内容(key不能重复)。
主要操作方法如下;
向集合中插入一组数据: public V put(K key,V value)
根据key取出value: public V get(Object key)
在Map中因为其组成较为特殊,所以本身不直接支持Iterator输出。
Set实例 entrySet() 步骤:Map 区分key和value。 Map.Entry实例 Iterator
Map.Entry:是Map的内部接口
|- 得到key: public K getKey()
|- 得到value: public V getValue()
操作方法:
|- 将全部的Map变为Set集合: public Set < Map.Entry < K,V >> entrySet()
|- 将全部的key变为Set集合: public Set < K > keySet()
|- 将全部的value变为Collection集合: public Collection < V > values()
3.6 . 1 、常用子类
1 、HashMap:是一个新的类,是在JDK 1 .2之后推出的,属于异步处理方式。
2 、Hashtable:是一个旧的类,是在JDK 1 .0时推出,属于同步处理方式
3 、TreeMap:按照key排序,同样key所在的类必须实现Comparable接口
3.6 . 2 、Hashtable子类 —— Properties
与Hashtable不同的是Properties主要操作的内容为字符串,表示的是属性操作。
Properties的主要方法:
设置属性: public Object setProperty(String key, String value)
取得属性:
|- public String getProperty(String key):根据key找到value,没找到返回null。
|- public String getProperty(String key,String defaultValue):如果没有找到,则指定默认值。
保存属性到文件: public void store(OutputStream out,String comments) throws IOException
从文件中读取内容: public void load(InputStream inStream) throws IOException
把文件保存成XML样式:
|- public void storeToXML(OutputStream os,String comment) throws IOException
从XML样式的文件之中读取属性:
|- public void loadFromXML(InputStream in) throws IOException,
InvalidPropertiesFormatException
3.6 . 3 、Map操作(HashMap)
例如:通过HashMap验证Map的使用
import java.util. * ;
public class ColDemo24 {
public static void main(String arg[]){
Map<String,String> m = new HashMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
String str = m.get("zhangsan") ;
System.out.println(str) ;
System.out.println(m.get("xxx")) ;
}
} ;
3.6 . 4 、Map操作(Hashtable)
import java.util. * ;
public class ColDemo25 {
public static void main(String arg[]){
Map<String,String> m = new Hashtable<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
String str = m.get("zhangsan") ;
System.out.println(str) ;
System.out.println(m.get("xxx")) ;
}
} ;
3.6 . 5 、Map操作(TreeMap)
import java.util. * ;
public class ColDemo26 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
String str = m.get("zhangsan") ;
System.out.println(str) ;
System.out.println(m.get("xxx")) ;
}
} ;
3.6 . 6 、Map操作(输出)
1 、使用Iterator输出Map中的全部数据(格式是固定的)
public Set < Map.Entry < K,V >> entrySet()
import java.util. * ;
public class ColDemo27 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
Set<Map.Entry<String,String>> list = m.entrySet() ;
Iterator<Map.Entry<String,String>> iter = list.iterator() ;
while(iter.hasNext()){
Map.Entry me = iter.next() ;
System.out.println(me.getKey() + " --> " + me.getValue()) ;
}
}
} ;
2 、将Map中全部的key输出
import java.util. * ;
public class ColDemo28 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
Set<String> list = m.keySet() ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3 、将Map中全部的value输出
import java.util. * ;
public class ColDemo29 {
public static void main(String arg[]){
Map<String,String> m = new TreeMap<String,String>() ;
m.put("zhangsan","123456") ;
m.put("lisi","234567") ;
m.put("wangwu","345678") ;
Collection<String> list = m.values() ;
Iterator<String> iter = list.iterator() ;
while(iter.hasNext()){
System.out.println(iter.next()) ;
}
}
} ;
3.6 . 7 、Map操作(问题)
例如:定义一个Person类,里面有name和age属性,之后在Map中保存一个person对象。
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
} ;
public class ColDemo30 {
public static void main(String args[]){
Map<String,Person> m = new HashMap<String,Person>() ;
m.put("zhangsan",new Person("张三",30)) ;
System.out.println(m.get("zhangsan")) ;
}
} ;
以上的运行结果,可以发现内容已经查找出来了。如果现在换个方式,使用Person对象表示张三呢?
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
} ;
public class ColDemo31 {
public static void main(String args[]){
Map<Person,String> m = new HashMap<Person,String>() ;
m.put(new Person("张三",30),"zhangsan") ;
System.out.println(m.get(new Person("张三",30))) ;
}
} ;
从运行结果,发现,里面没有任何的内容,返回一个“ null ”。此时再修改代码:
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
} ;
public class ColDemo32 {
public static void main(String args[]){
Map<Person,String> m = new HashMap<Person,String>() ;
Person p = new Person("张三",30) ;
m.put(p,"zhangsan") ;
System.out.println(m.get(p)) ;
}
} ;
以上可以找到代号。
从以上代码中可以发现问题:
如果使用字符串作为key,就算是匿名对象也是可以找得到
如果自己编写了一个key,则如果使用匿名对象则无法找到。
因为在对象上有一个对象自己的编码,那么如果要想使用此编码,则必须在对象所在的类中覆写Object类中的hashCode()方法。
import java.util. * ;
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
public boolean equals(Object obj){
if(this==obj){
return true ;
}
if(!(obj instanceof Person)){
return false ;
}
Person p = (Person)obj ;
if(this.name.equals(p.name)&&this.age==p.age){
return true ;
}else{
return false ;
}
}
public int hashCode(){
// 正常来说,应该为hashCode的产生自己定义一个公式
return this.age * this.name.hashCode() ;
}
} ;
public class ColDemo33 {
public static void main(String args[]){
Map<Person,String> m = new HashMap<Person,String>() ;
m.put(new Person("张三",30),"zhangsan") ;
System.out.println(m.get(new Person("张三",30))) ;
}
} ;
3.6 . 8 、Properties操作
1 、向Properties中设置属性,并取得属性
import java.util. * ;
public class ColDemo35 {
public static void main(String args[]){
Properties pro = new Properties() ;
pro.setProperty("BJ","BeiJing") ;
pro.setProperty("NJ","NanJing") ;
pro.setProperty("SH","ShangHai") ;
System.out.println(pro.getProperty("BJ")) ;
System.out.println(pro.getProperty("XJ")) ;
System.out.println(pro.getProperty("XJ","nofound")) ;
}
} ;
2 、将全部的属性保存在普通文件之中
import java.util. * ;
import java.io. * ;
public class ColDemo36 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.setProperty("BJ","BeiJing") ;
pro.setProperty("NJ","NanJing") ;
pro.setProperty("SH","ShangHai") ;
pro.store(new FileOutputStream(new File("e:\\pro.ini")),"AREA") ;
}
} ;
3 、从文件中读取属性
import java.util. * ;
import java.io. * ;
public class ColDemo37 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.load(new FileInputStream(new File("e:\\pro.ini"))) ;
System.out.println(pro.getProperty("BJ")) ;
}
} ;
4 、将属性按照XML样式的风格进行保存
import java.util. * ;
import java.io. * ;
public class ColDemo38 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.setProperty("BJ","BeiJing") ;
pro.setProperty("NJ","NanJing") ;
pro.setProperty("SH","ShangHai") ;
pro.storeToXML(new FileOutputStream(new File("e:\\pro.xml")),"AREA") ;
}
} ;
5 、将属性从XML中读取出来
import java.util. * ;
import java.io. * ;
public class ColDemo39 {
public static void main(String args[]) throws Exception{
Properties pro = new Properties() ;
pro.loadFromXML(new FileInputStream(new File("e:\\pro.xml"))) ;
System.out.println(pro.getProperty("BJ")) ;
}
} ;
现在操作属性的时候基本上都是以XML样式为准。
3.7 、实例
3.7 . 1 、实例一
一个人有多本书,一本书属于一个人。
package org.lxh.demo1;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
class Person {
private String name;
private int age;
private List<Book> listBooks;
public Person() {
this.listBooks = new ArrayList<Book>();
}
public Person(String name, int age) {
this();
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;
}
public List<Book> getlistBooks() {
return listBooks;
}
public void setlistBooks(List<Book> listBooks) {
this.listBooks = listBooks;
}
}
class Book {
private String title;
private Person person;
public Book(String title) {
super();
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
public class Demo01 {
public static void main(String[] args) {
Person per = new Person("张三", 30);
Book b1 = new Book("JAVA");
Book b2 = new Book("C");
Book b3 = new Book("NET");
per.getlistBooks().add(b1);
per.getlistBooks().add(b2);
per.getlistBooks().add(b3);
b1.setPerson(per);
b2.setPerson(per);
b3.setPerson(per);
System.out.println("姓名:" + per.getName() + ",年龄:" + per.getAge());
Iterator<Book> iter = per.getlistBooks().iterator();
while (iter.hasNext()) {
System.out.println("\t|- " + iter.next().getTitle());
}
}
}
3.7 . 2 、实例二
一个学生可以选多个课程,一个课程可以多个学生参加。
package org.lxh.demo2;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
class Student {
private String name;
private List<Course> listCourses;
public Student() {
this.listCourses = new ArrayList<Course>();
}
public Student(String name) {
this();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getlistCourses() {
return listCourses;
}
public void setlistCourses(List<Course> listCourses) {
this.listCourses = listCourses;
}
}
class Course {
private String name;
public List<Student> listStudents;
public Course() {
this.listStudents = new ArrayList<Student>();
}
public Course(String name) {
this();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getlistStudents() {
return listStudents;
}
public void setlistStudents(List<Student> listStudents) {
this.listStudents = listStudents;
}
}
public class Demo02 {
public static void main(String[] args) {
Student s1 = new Student("张三");
Student s2 = new Student("李四");
Student s3 = new Student("王五");
Student s4 = new Student("赵六");
Student s5 = new Student("孙七");
Course c1 = new Course("JAVA");
Course c2 = new Course("Oracle");
// 设置关系
s1.getlistCourses().add(c1);
c1.getlistStudents().add(s1);
s2.getlistCourses().add(c1);
c1.getlistStudents().add(s2);
s3.getlistCourses().add(c1);
c1.getlistStudents().add(s3);
s4.getlistCourses().add(c2);
c2.getlistStudents().add(s4);
s5.getlistCourses().add(c2);
c2.getlistStudents().add(s5);
s1.getlistCourses().add(c2);
c2.getlistStudents().add(s1);
s2.getlistCourses().add(c2);
c2.getlistStudents().add(s2);
System.out.println("学生:" + s1.getName());
Iterator<Course> iter1 = s1.getlistCourses().iterator();
while (iter1.hasNext()) {
System.out.println("\t|- " + iter1.next().getName());
}
System.out.println("---------------------------------");
System.out.println("课程:" + c2.getName());
Iterator<Student> iter2 = c2.getlistStudents().iterator();
while (iter2.hasNext()) {
System.out.println("\t|- " + iter2.next().getName());
}
}
}
4 、总结
1 、Collection(保存单个对象)
List:允许有重复元素,拥有更多的操作方法
|- ArrayList:新的、异步处理
|- Vector:旧的, 同步处理,支持Iterator和Enumeration两种输出
|- Stack:入栈、出栈
Set:不允许有重复元素,靠hashCode和equals方法来区分重复元素
|- HashSet:无序
|- TreeSet:有序、按照Comparable指定的规则排序
常用方法:add()、iterator()、remove
2 、Map(保存一对对象)
HashMap:新的类,异步处理
Hashtable:旧的类,同步处理
|- Properties(属性操作),可以将属性保存在文件之中
TreeMap:排序操作类,此类按key排序,使用Comparable完成
主要方法:put、get、entrySet
Map不能直接使用Iterator输出,必须转换成Set,通过Map.Entry分离key和value
3 、Iterator
输出接口,只要是类集都使用此接口输出,一般情况下很少有删除代码出现
主要方法:
|- 判断是否有下一个元素: public boolean hasNext()
|- 取出当前元素: public Object next()
子接口:ListIterator
|- 双向输出,但是此接口只能通过List实例化
4 、Enumeration接口
最早的输出接口,现在部分代码上依然使用