您的位置 首页 java

JAVA学习基础之JAVA类集

第十三章、 java 类集

JAVA 中必须掌握的知识点,会开发的:

1、面向对象; 2、JAVA的类集; 3、 JAVAIO ; 4、 JDBC

13-1、认识类集、Collection接口

类集实际上就是一个动态的对象数组,与一般的对象数组不同,类集中的对象内容可以任意扩充。

类集的特征:

·这种框架是高性能的;

·框架必须允许不同类型的类集以相同的方式和高度互操作方式工作;

·类集必须是容易扩展和修改的;

对象数组中包含一组对象,但是对象数组使用的时候存在一个长度的限制,那么类集是专门解决这种限制的,使用类集可以方便的向数组中增加任意多个数据。

对象数组的操作中基本上都要保证对象类型的一致性,对于类集而言本身其内部的元素也应该保持一致,不管是何种类型的数据,所有的操作方式都应该是一样的。

类集框架主要接口

NO

接口

描述

1

Collection

是存放一组单值的最大接口,所谓的单值是指集合中的每个元素都是一个对象,一般很少会直接使用此接口直接操作。

2

List

Collection 接口的子接口,也是最常用的接口,此接口对Collection接口进行了大量的扩充,里面的内容是允许重复的。

3

Set

是Collection接口的子类,没有对Collection接口进行扩充,里面不允许存放重复内容。

4

Map

Map是存放一对值的最大接口,即,接口中的每个元素都是一对,以keyvalue的形式保存

5

iterator

集合的输出接口,用于输出集合中的内容,只能进行从前到后的单向输出。

6

ListIterator

是Iterator的子接口,可以进行双向输出。

7

Enumeration

是最早的输出接口,用于输出指定集合中的内容。

8

SortedMap

存放一对值的排序接口,实现此接口的集合类,里面的内容按照key排序,使用比较器排序。

9

SortedSet

单值的排序接口,实现此接口的集合类,里面的内容是可以排序的,使用比较器排序。

10

Queue

队列接口,此接口的子类可以实现队列操作。

11

Map.Entry

Map.Entry的内部接口,每个Map.Entry对象都保存着一对keyvalue的内容,每个Map接口中都保存多个Map.Entry接口实例。

JAVA学习基础之JAVA类集

Collection接口 的定义:

·Collection是保存单值集合的最大父接口;

·Collection接口定义:

·public interface Collection<E> Extends Iterable<E>

·JDK1.5之后为Collection接口增加了泛型声明;

所有的类集操作都在java.util包中。

Collection接口的方法定义

NO

方法

类型

描述

1

public Boolean add(E o)

普通

向集合中插入对象

2

public Boolean addAll(Collection<? Extends E> c)

普通

将一个集合的内容插入进来

3

public void clear()

普通

清除此集合中的所有元素

4

public boolean conlains(Object o)

普通

判断某一个对象是否在集合中存在

5

public Boolean containsAll(Collection<?> c)

普通

判断一组对象是否在集合中存在

6

public Boolean equals(Object o)

普通

对象比较

7

public int hashCode ()

普通

哈希码

8

public Boolean isEmpty()

普通

集合是否为空

9

public Iterator<E> iterator()

普通

为Iterator接口实例化

10

public Boolean remove(Object o)

普通

删除指定对象

11

public Boolean removeAll(Collection<?> c)

普通

删除一组对象

12

public Boolean retainAll(Collection<?> c)

普通

保存指定内容

13

public int size()

普通

求出集合的大小

14

public Object[] toArray ()

普通

将一个集合变为对象数组

15

public <T> T[] toArray(T[] a)

普通

指定好返回的对象数组类型

Collection接口的使用注意:

·在一般的开发中,往往很少去直接使用Collection接口进行开发,而基本上都是使用其子接口。 子接口 主要有:List、Set、Queue、SortedSet。

之所以不使用Collection接口也是JAVA的逐步发展形成的,最早的时候实际上Collection接口被广泛使用,因为EJB技术的支持,在EJB2.x中大量的使用了Collection接口,但是随着发展,SUN公司开始将这些标准进行逐步的规范化,所以在 SUN 一个开源—宠物商店,基本上就不再直接使用Collection了,而是使用List或Set,这样来说可以更加清楚的表示出操作的类型。

Collection子接口的定义:Collection接口虽然是集合的最大接口,但是如果直接使用Collection接口进行操作的话,则表示的操作意义不明确,所以在JAVA开发中已经不提倡直接使用Collection接口了,主要的子接口如下:

·List接口:可以存放重复的内容

·Set接口:不能存放重复的内容,所有的重复内容是靠hashCode()和equals()两个方法区分的

·Queue:队列接口

·SortedSet接口:可以对集合中的数据进行排序

13-2、JAVA类集—List接口

Collection下分为很多的子接口,其中有一个List接口,List接口中可以存放任意的数据,而且在List接口中内容是允许重复的。

List是Collection的子接口,里面可以保存各个重复的内容,此接口的定义如下:

·public interface List<E> extends Collection<E>

List接口的扩展方法

NO

方法

类型

描述

1

public void add(int index,E element)

普通

在指定位置增加元素

2

public Boolean addAll(int index,Collection<? extends E> c)

普通

在指定位置增加一组元素

3

E get(int index)

普通

返回指定位置的元素

4

public int indexOf(Object o)

普通

查找指定元素的位置

5

public int lastIndexOf(Object o)

普通

从后向前查找指定元素的位置

6

public ListIterator<E> listIterator()

普通

为ListIterator接口实例化

7

public E remove(int index)

普通

按指定的位置删除元素

8

public List<E> subList(int fromIndex,int toIndex)

普通

取出集合中的子集合

9

public E set(int index,E element)

普通

替换指定位置的元素

List接口的常用子类——ArrayList

ArrayList是List子类,可以直接通过对象的多态性,为List接口实例化,此类的定义如下:

public class ArrayList<E> extends AbstractList <E> implements List<E>,RandomAccess,Cloneable, Serializable

AbstractList类的定义如下:

public abstract class Abstract List<E> extends AbstractCollection<E> implements List<E>

如果要想使用接口,则肯定要使用对象的多态性进行实例化的操作,那么对于List接口本身也是一样的。

ArrayList是List接口中最常用的子类。

import java.util.ArrayList ;

import java.util.List ;

public class ArrayListDemo01{

public static void main(String args[]){

List<String> allList = null ;

allList = new ArrayList<String>() ; // 指定操作的 泛型 为String

allCollection = new ArrayList<String>() ; // 指定一个集合

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(0,”World”) ; // 在第一个位置上添加新的内容

System.out.println(allList) ;

}

};

在指定位置上增加一组数据:

import java.util.ArrayList ;

import java.util.List ;

import java.util.Collection ;

public class ArrayListDemo01{

public static void main(String args[]){

List<String> allList = null ;

Collection<String> allCollection = null ;

allList = new ArrayList<String>() ; // 指定操作的泛型为String

allCollection = new ArrayList<String>() ; // 指定一个集合

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(0,”World”) ; // 在第一个位置上添加新的内容

System.out.println(allList) ;

allCollection.add(“LXH”) ; // 向Collection中加入内容

allCollection.add(“www.mldn.cn”) ;

allList.addAll(allCollection) ;

allList.addAll(0,allCollection) ;

System.out.println(allList) ;

}

};

既然可以增加数据,那么自然也可以删除数据:

·List中存在两种删除:根据对象内容、根据对象的编号

import java.util.ArrayList ;

import java.util.List ;

public class ArrayListDemo02{

public static void main(String args[]){

List<String> allList = null ;

allList = new ArrayList<String>() ; // 指定操作的泛型为String

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(0,”World”) ; // 在第一个位置上添加新的内容

allList.add(“MLDN”) ; // 向Collection中加入内容

allList.add(“www.mldn.cn”) ;

allList.remove(0) ; // 删除第一个元素,指定删除的位置

allList.remove(“Hello”) ; // 此方法由Collection接口继承而来

System.out.println(allList) ;

}

};

集合中的内容可以添加,可以删除,那么实际上最重要的就是输出。

·在List接口中提供了get()方法,利用此方法就可以完成输出。

·通过循环完成输出,循环的次数由size()方法取得。

import java.util.ArrayList ;

import java.util.List ;

public class ArrayListDemo03{

public static void main(String args[]){

List<String> allList = null ;

allList = new ArrayList<String>() ; // 指定操作的泛型为String

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(0,”World”) ; // 在第一个位置上添加新的内容

allList.add(“MLDN”) ; // 向Collection中加入内容

allList.add(“www.mldn.cn”) ;

System.out.print(“由前向后输出:”) ;

for(int i=0;i<allList.size();i++){

System.out.print(allList.get(i) + “、”) ;

}

System.out.print(“n由后向前输出:”) ;

for(int i=allList.size()-1;i>=0;i–){

System.out.print(allList.get(i) + “、”) ;

}

}

};

此输出方式是List接口所独有的,而其他接口是没有的,尤其是Collection中是没有根据索引取出内容的操作。

import java.util.ArrayList ;

import java.util.List ;

public class ArrayListDemo04{

public static void main(String args[]){

List<String> allList = null ;

allList = new ArrayList<String>() ; // 指定操作的泛型为String

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(0,”World”) ; // 在第一个位置上添加新的内容

allList.add(“MLDN”) ; // 向Collection中加入内容

allList.add(“www.mldn.cn”) ;

String str[] = allList.toArray(new String[]{}) ; // 指定好类型

System.out.print(“指定数组类型:”) ;

for(int i=0;i<str.length;i++){

System.out.print(str[i] + “、”) ;

}

System.out.print(“n返回对象数组:”) ;

Object obj [] = allList.toArray() ; // 返回Object类型

for(int i=0;i<obj.length;i++){

String temp = (String)obj[i] ; // 进行向下转型

System.out.print(temp + “、”) ;

}

}

};

既然已经完成基本的输出的功能,集合中还有以下的几个操作:

·判断集合是否为空:boolean isEmpty()

·截取部分集合:List<E> subList(int fromIndex,int toIndex),List接口扩充

·查找指定的对象是否存在:int indexOf(Object o),如果查找到则返回位置,否则返回-1

·查找是否存在:boolean contains(Object o)

import java.util.ArrayList ;

import java.util.List ;

public class ArrayListDemo05{

public static void main(String args[]){

List<String> allList = null ;

allList = new ArrayList<String>() ; // 指定操作的泛型为String

System.out.println(“集合操作前是否为空?” + allList.isEmpty()) ;

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(0,”World”) ; // 在第一个位置上添加新的内容

allList.add(“MLDN”) ; // 向Collection中加入内容

allList.add(“www.mldn.cn”) ;

System.out.println(allList.contains(“Hello”)?””Hello”字符串存在!” : “”Hello”字符串不存在!”) ;

List<String> allSub = allList.subList(2,3) ; // 字符串截取

System.out.println(“集合截取:”) ;

for(int i=0;i<allSub.size();i++){

System.out.print(allSub.get(i) + “、”) ;

}

System.out.println(“MLDN字符串的位置:” + allList.indexOf(“MLDN”)) ;

System.out.println(“集合操作后是否为空?” + allList.isEmpty()) ;

}

};

挽救的子类:Vector

在List接口中还有一个子类:Vector, Vector 类属于一个挽救的子类,从整个JAVA的集合发展历史来看,Vector算是一个元老级的类,在JDK1.0的时候已经存在此类.但是到了JAVA2(JDK1.2)之后重点强调了集合框架的概念,所以先后定义了很多的新接口(如:List等),但是考虑到了一大部分的人已经习惯了使用Vector类,所以JAVA的设计者,就让Vector类多实现了一个List接口,这才将其保留下来。但是因为其是List子类,所以Vector类的使用与之前的并没有太大的区别。

Vector类的定义:

·public class Vector<E> extends AbstractList<E>implements List<E>,RandomAccess,Cloneable,Serializable

import java.util.Vector ;

import java.util.List ;

public class VectorDemo01{

public static void main(String args[]){

List<String> allList = null ;

allList = new Vector<String>() ; // 指定操作的泛型为String

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(“Hello”) ; // 此方法由Collection接口而来

allList.add(0,”World”) ; // 在第一个位置上添加新的内容

allList.add(“MLDN”) ; // 向Collection中加入内容

allList.add(“www.mldn.cn”) ;

for(int i=0;i<allList.size();i++){

System.out.print(allList.get(i) + “、”) ;

}

}

};

因为Vector类本身属于旧的类,所以在类中也提供了很多重复的方法。

增加元素:public void addElement(E obj)此方法是最早的增加元素的操作,之后此方法的功能与add()方法是一致的。

import java.util.Vector ;

import java.util.List ;

public class VectorDemo02{

public static void main(String args[]){

Vector<String> allList = null ;

allList = new Vector<String>() ; // 指定操作的泛型为String

allList.addElement(“Hello”) ; // 此方法由Collection接口而来

allList.addElement(“MLDN”) ; // 向Collection中加入内容

allList.addElement(“www.mldn.cn”) ;

for(int i=0;i<allList.size();i++){

System.out.print(allList.get(i) + “、”) ;

}

}

};

那么ArrayList与Vector我们应该使用哪个类呢?

ArrayList与Vector的区别

NO

比较点

ArrayList

Vector

1

推出时间

JDK 1.2之后推出的,属于新的操作类

JDK1.0时推出,属于旧的操作类

2

性能

采用异步处理方式,性能更高

采用同步处理方式,性能较低

3

线程安全

属于非线程安全的操作类

属于 线程 安全的操作类

4

输出

只能使用Iterator、foreach输出

可以使用Iterator、 foreach 、Enumeration输出

13-3、JAVA类集—LinkedList类

13-3-1、LinkedList子类与Queue接口

LinkedList表示的是一个链表的操作类,此类定义如下:

·public class LinkedList<E> extends AbstractSequentialList<E>implements List<E>,Queue<E>,Cloneable,Serializable

Queue接口是Collection的子接口,此接口定义如下:

·public interface Queue<E> extends Collection<E>

Queue接口定义的方法

NO

方法

类型

描述

1

public E element()

普通

找到 链表 的表头

2

public Boolean offer(E o)

普通

将指定元素增加到链表的结尾

3

public E peek()

普通

找到但并不删除链表的头

4

public E poll()

普通

找到并删除此链表的头

5

public E remove()

普通

检索并移除表头

LinkedList中操作链表的部分方法

NO

方法

类型

描述

1

public void addFirst(E o)

普通

在链表开头增加元素

2

public void addLast(E o)

普通

在链表结尾增加元素

3

public Boolean offer(E o)

普通

将指定元素增加到链表的结尾

4

public E removeFirst()

普通

删除链表的第一个元素

5

public E removeLast()

普通

删除链表的最后一个元素

本身大量的扩充了Queue接口和List接口的操作,所以,在使用时最好直接使用LinkedList类完成操作。

为链表的开头和结尾增加数据

import java.util.LinkedList ;

public class LinkedListDemo01{

public static void main(String args[]){

LinkedList<String> link = new LinkedList<String>() ;

link.add(“A”) ; // 增加元素

link.add(“B”) ; // 增加元素

link.add(“C”) ; // 增加元素

System.out.println(“初始化链表:” + link) ;

link.addFirst(“X”) ; // 在开头增加数据

link.addLast(“Y”) ; // 在结尾增加数据

System.out.println(“增加头和尾之后的链表:” + link) ;

}

};

对于链表也可以找到其表头:

import java.util.LinkedList ;

public class LinkedListDemo02{

public static void main(String args[]){

LinkedList<String> link = new LinkedList<String>() ;

link.add(“A”) ; // 增加元素

link.add(“B”) ; // 增加元素

link.add(“C”) ; // 增加元素

System.out.println(“1-1、element()方法找到表头:” + link.element()) ;

System.out.println(“1-2、找完之后的链表的内容:” + link) ;

System.out.println(“2-1、peek()方法找到表头:” + link.peek()) ;

System.out.println(“2-2、找完之后的链表的内容:” + link) ;

System.out.println(“3-1、poll()方法找到表头:” + link.poll()) ;

System.out.println(“3-2、找完之后的链表的内容:” + link) ;

}

};

既然此类实现了Queue接口,那么就可以按照队列的方式进行FIFL的操作:

import java.util.LinkedList ;

public class LinkedListDemo03{

public static void main(String args[]){

LinkedList<String> link = new LinkedList<String>() ;

link.add(“A”) ; // 增加元素

link.add(“B”) ; // 增加元素

link.add(“C”) ; // 增加元素

System.out.print(“以FIFO的方式输出:”) ;

for(int i=0;i<=link.size()+1;i++){

System.out.print(link.poll() + “、”) ;

}

}

};

13-4、JAVA类集—Set接口

Set接口也是Collection接口的子接口,但是与Collection或List接口不同的是,Set接口中不能加入重复的元素。

Set接口的定义:

·public interface Set<E> extends Collection<E>

Set接口的主要方法与Collection是一致的;

Set接口的实现无法像List接口那样进行双向输出;

Set接口的常用子类:

·散列存放:HashSet;使用散列的方式存放内容,本身没有顺序。

·有序存放:TreeSet

使用HashSet输入数据:

import java.util.HashSet ;

import java.util.Set ;

public class HashSetDemo01{

public static void main(String args[]){

Set<String> allSet = new HashSet<String>() ;

allSet.add(“A”) ; // 增加内容

allSet.add(“B”) ; // 增加内容

allSet.add(“C”) ; // 增加内容

allSet.add(“C”) ; // 重复内容

allSet.add(“C”) ; // 重复内容

allSet.add(“D”) ; // 增加内容

allSet.add(“E”) ; // 增加内容

System.out.println(allSet) ;

}

};

以上代码运行后显示的内容是无序排列的。而List接口的内容插入的顺序就是其保存的顺序。

如果希望所有的内容可以自动进行排序的操作,则可以使用Set中的第二个子类TreeSet。

import java.util.TreeSet ;

import java.util.Set ;

public class TreeSetDemo01{

public static void main(String args[]){

Set<String> allSet = new TreeSet<String>() ;

allSet.add(“C”) ; // 增加内容

allSet.add(“C”) ; // 重复内容

allSet.add(“C”) ; // 重复内容

allSet.add(“D”) ; // 增加内容

allSet.add(“B”) ; // 增加内容

allSet.add(“A”) ; // 增加内容

allSet.add(“E”) ; // 增加内容

System.out.println(allSet) ;

}

};

TreeSet子类是可以排序的。

13-5、JAVA类集—排序及重复元素说明

TreeSet类的内容是可以排序的,那么现在给出任意一个类,观察能否进行排序的操作:

import java.util.Set ;

import java.util.TreeSet ;

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 TreeSetDemo02{

public static void main(String args[]){

Set<Person> allSet = new TreeSet<Person>() ;

allSet.add(new Person(“张三”,30)) ;

allSet.add(new Person(“李四”,31)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“赵六”,33)) ;

allSet.add(new Person(“孙七”,33)) ;

System.out.println(allSet) ;

}

};

执行时出现了以下的错误:

Exception in thread “main” java.lang.ClassCastException:Person cannot be cast to Java.lang.Comparable

at java.util.TreeMap.put(Unknown Source)

at java.util.TreeSet.add(Unknown Source)

at TreeSetDemo02.main(TreeSetDemo02.java:18)

Comparable之前曾经讲解过主要是进行排序的操作接口,一个对象数组要想排序,则依靠Comparable接口完成,那么对于TreeSet也一样,如果要想使用TreeSet进行排序的操作,则对象所在的类也必须实现Comparable接口。

import java.util.Set ;

import java.util.TreeSet ;

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 TreeSetDemo03{

public static void main(String args[]){

Set<Person> allSet = new TreeSet<Person>() ;

allSet.add(new Person(“张三”,30)) ;

allSet.add(new Person(“赵六”,25)) ;

allSet.add(new Person(“孙七”,25)) ;

allSet.add(new Person(“李四”,31)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

System.out.println(allSet) ;

}

};

String类既然可以使用TreeSet排序,则String中肯定已经实现了Comparable接口。

此时是可以排序了,但是结果有问题:

[姓名:赵六;年龄:25, 姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32]

发现此时去掉了重复的元素(在程序中,王五插入了三个),但是依靠的是Comparable接口完成的。孙七没有加进来,因为两个的年龄是完全一样的,而此时的Comparable接口比较的只是年龄,所以为了保证正确,所有的属性都应该进行比较:

import java.util.Set ;

import java.util.TreeSet ;

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 this.name.compareTo(per.name) ; // 调用String中的compareTo()方法

}

}

};

public class TreeSetDemo04{

public static void main(String args[]){

Set<Person> allSet = new TreeSet<Person>() ;

allSet.add(new Person(“张三”,30)) ;

allSet.add(new Person(“赵六”,25)) ;

allSet.add(new Person(“孙七”,25)) ;

allSet.add(new Person(“李四”,31)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

System.out.println(allSet) ;

}

};

运行结果:

[姓名:孙七;年龄:25, 姓名:赵六;年龄:25, 姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32]

此时去掉的重复元素是按姓名取消重复元素的。

现在采用HashSet接口写入数据,看看结果:

import java.util.Set ;

import java.util.HashSet ;

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 RepeatDemo01{

public static void main(String args[]){

Set<Person> allSet = new HashSet<Person>() ;

allSet.add(new Person(“张三”,30)) ;

allSet.add(new Person(“赵六”,25)) ;

allSet.add(new Person(“孙七”,25)) ;

allSet.add(new Person(“李四”,31)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

System.out.println(allSet) ;

}

};

运行结果:

[姓名:王五;年龄:32, 姓名:李四;年龄:31, 姓名:王五;年龄:32, 姓名:张三;年龄:30, 姓名:王五;年龄:32, 姓名:赵六;年龄:25, 姓名:孙七;年龄:25]

此时,程序并没有去掉重复的元素,那么重复元素该如何取消呢?

如果要想取消掉重复元素,则需要Object类中的两个方法帮助:

·hashCode():表示一个唯一的编码,一般通过计算表示

·equals():进行对象的比较操作

import java.util.Set ;

import java.util.HashSet ;

class Person{

private String name ;

private int age ;

public Person(String name,int age){

this.name = name ;

this.age = age ;

}

public boolean equals(Object obj){ // 覆写equals,完成对象比较

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(){

return this.name.hashCode() * this.age ; // 定义一个公式

}

public String toString(){

return “姓名:” + this.name + “;年龄:” + this.age ;

}

};

public class RepeatDemo02{

public static void main(String args[]){

Set<Person> allSet = new HashSet<Person>() ;

allSet.add(new Person(“张三”,30)) ;

allSet.add(new Person(“赵六”,25)) ;

allSet.add(new Person(“孙七”,25)) ;

allSet.add(new Person(“李四”,31)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

allSet.add(new Person(“王五”,32)) ;

System.out.println(allSet) ;

}

};

如果要想使用Set,则就必须注意以上的两个问题。

总结:

·一个好的类应该覆写Object类中的equals()、hashCode()、toString()三个方法,实际上在String中已经全部覆写完成了

·Set接口依靠hashCode()和equals()完成重复元素的判断,关于这一点在以后的Map接口中也有体现

·TreeSet依靠Comparable接口完成排序的操作

13-6、JAVA类集—SortedSet接口

从TreeSet类的定义中可以发现,TreeSet里实现了SortedSet接口,此接口主要是用于排序操作的,即:实现此接口的子类都属于排序的子类。SortedSet接口的定义如下:

·public interface SortedSet<E> extends Set<E>

SortedSet接口中定义的方法

NO

方法

类型

描述

1

public Comparator<? Super E> comparator()

普通

返回与排序有关联的比较器

2

public E first()

普通

返回集合中的第一个元素

3

public SortedSet<E> headset(E toElement)

普通

返回从开始到指定元素的集合

4

public E last()

普通

返回最后一个元素

5

public SortedSet<E> subset(E fromElement,E toElement)

普通

返回指定对象间的元素

6

public SortedSet<E> tailSet(E fromElement)

普通

从指定元素到最后

操作实例:

import java.util.SortedSet ;

import java.util.TreeSet ;

public class TreeSetDemo05{

public static void main(String args[]){

SortedSet<String> allSet = new TreeSet<String>() ; //

allSet.add(“A”) ; // 增加内容

allSet.add(“B”) ; // 增加内容

allSet.add(“C”) ; // 增加内容

allSet.add(“C”) ; // 增加内容

allSet.add(“C”) ; // 增加内容

allSet.add(“D”) ; // 增加内容

allSet.add(“E”) ; // 增加内容

System.out.println(“第一个元素:” + allSet.first()) ;

System.out.println(“最后一个元素:” + allSet.last()) ;

System.out.println(“headSet元素:” + allSet.headSet(“C”)) ;

System.out.println(“tailSet元素:” + allSet.tailSet(“C”)) ;

System.out.println(“subSet元素:” + allSet.subSet(“B”,”D”)) ;

}

};

13-7、JAVA类集—Iterator接口

在类集中提供了以下四种常见的输出方式:

·Iterator:迭代输出,是使用最多的输出方式

·ListIterator:是Iterator的子接口,专门用于输出List中的内容

·foreach输出:JDK1.5之后提供的新功能,可以输出数组或集合

·Enumeration输出:是一个旧的接口,功能与Iterator类似

JAVA学习基础之JAVA类集

对于Iterator而言,因为其本身是一个接口,所以要想实例化则必须依靠Collection接口完成。

Iterator<E> iterator()

使用Iterator输出:

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class IteratorDemo01{

public static void main(String args[]){

List<String> all= new ArrayList<String>() ; //

all.add(“hello”) ;

all.add(“_”) ;

all.add(“world”) ;

Iterator<String> iter = all.iterator() ; // 为Iterator接口实例化

while(iter.hasNext()){ // 判断是否有内容

System.out.println(iter.next()) ; // 输出内容

}

}

};

以上的操作代码属于Iterator的标准做法。

在Iterator接口中提供了remove()方法,此方法的功能是删除当前的对象:

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class IteratorDemo02{

public static void main(String args[]){

List<String> all= new ArrayList<String>() ; //

all.add(“hello”) ;

all.add(“_”) ;

all.add(“world”) ;

Iterator<String> iter = all.iterator() ; // 为Iterator接口实例化

while(iter.hasNext()){ // 判断是否有内容

String str = iter.next() ;

if(“_”.equals(str)){

iter.remove() ; // 删除元素

}else{

System.out.println(str) ; // 输出内容

}

}

System.out.println(“删除之后的集合:” + all) ;

}

};

在实际中Iterator是很少调用删除操作的,因为其本身的功能就是输出内容,当然,对于删除操作也有以下的一个注意点:

·List接口本身存在删除方法:remove

如果在使用迭代输出的过程中使用了List中的remove()执行删除操作,则代码将出现问题。

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class IteratorDemo03{

public static void main(String args[]){

List<String> all= new ArrayList<String>() ; //

all.add(“hello”) ;

all.add(“_”) ;

all.add(“world”) ;

Iterator<String> iter = all.iterator() ; // 为Iterator接口实例化

while(iter.hasNext()){ // 判断是否有内容

String str = iter.next() ;

if(“_”.equals(str)){

all.remove(str) ; // 删除元素

}else{

System.out.println(str) ; // 输出内容

}

}

System.out.println(“删除之后的集合:” + all) ;

}

};

在使用Iterator输出时,不要使用集合类中的remove()方法,而只能使用Iterator接口中的remove方法。

总结:

·Iterator接口的功能是从前向后输出,属于单向的输出

·Iterator的主要功能就是完成迭代输出操作的

·在使用Iterator的时候最好不要删除数据

13-8、JAVA类集—ListIterator接口

Iterator接口的主要功能是由前向后单向输出,而此时如果想实现由后向前或是由前向后的双向输出,则就必须使用Iterator的子接口——ListIterator。ListIterator接口定义如下:

·public interface ListIterator<E> extends Iterator<E>

虽然此接口可以进行双向的输出,但是遗憾的是Collection接口中并没有定义可以为此类实例化的操作,只有List接口中才存在了ListIterator接口的实例化操作。

范例:完成双向输出操作。

import java.util.ArrayList ;

import java.util.List ;

import java.util.ListIterator ;

public class ListIteratorDemo01{

public static void main(String argsp[]){

List<String> all = new ArrayList<String>() ;

all.add(“hello”) ;

all.add(“_”) ;

all.add(“world”) ;

ListIterator<String> iter = all.listIterator() ;

System.out.print(“由前向后输出:”) ;

while(iter.hasNext()){

String str = iter.next() ;

System.out.print(str + “、”) ;

}

System.out.print(“n由后向前输出:”) ;

while(iter.hasPrevious()){

String str = iter.previous() ;

System.out.print(str + “、”) ;

}

}

};

此时,已经完成了双向的输出操作。

但是,在使用此操作的时候一定要注意一点,一定要先进行由前后输出,之后才能进行由后向前的输出。

使用ListIterator还可以进行增加及替换元素:

·add()

·set()

import java.util.ArrayList ;

import java.util.List ;

import java.util.ListIterator ;

public class ListIteratorDemo02{

public static void main(String argsp[]){

List<String> all = new ArrayList<String>() ;

all.add(“hello”) ;

all.add(“_”) ;

all.add(“world”) ;

ListIterator<String> iter = all.listIterator() ;

System.out.print(“由前向后输出:”) ;

while(iter.hasNext()){

String str = iter.next() ;

System.out.print(str + “、”) ;

iter.set(“LI – ” + str) ; // 修改内容

}

System.out.print(“n由后向前输出:”) ;

iter.add(“LXH”);

while(iter.hasPrevious()){

String str = iter.previous() ;

System.out.print(str + “、”) ;

}

}

};

总结:

·如果要想使用ListIterator则只能依靠List接口完成

·如果要进行由后向前的输出,则只能先进行由前向后的输出

·对于此接口中的增加及修改操作了解即可

13-9、JAVA类集—foreach及Enumeration接口

JDK1.5之后增加了许多的功能,其中foreach可以输出数组,实际上foreach语法中也同样支持集合的输出操作:

import java.util.ArrayList;

import java.util.List;

public class ForeachDemo01{

public static void main(String args[]){

List<String> all = new ArrayList<String>() ;

all.add(“hello”) ;

all.add(“_”) ;

all.add(“world”) ;

for(String str:all){

System.out.print(str + “、”) ;

}

}

};

实际上Iterator属于一个新的输出接口,在最早的JAVA刚出来的时候如果要想输出,使用Enumeration接口完成输出。

但是在JAVA中因为存在发展的历史问题,所以有些地方还会使用到Enumeration输出。

而且必须注意的是在使用Enumeration输出的时候一般都是直接操作Vector类完成的。

import java.util.Vector;

import java.util.Enumeration;

public class EnumerationDemo01{

public static void main(String args[]){

Vector<String> all = new Vector<String>() ;

all.add(“hello”) ;

all.add(“_”) ;

all.add(“world”) ;

Enumeration<String> enu = all.elements() ;

while(enu.hasMoreElements()){ //判断是否有内容,hasNext()

System.out.print(enu.nextElement() + “、”) ; // 输出元素:next()

}

}

};

总结:

·在所有的输出操作中,以Iterator接口为最标准的输出操作

·在部分旧的操作中Enumeration依然存在

13-10、JAVA类集—Map接口

之前接触的Collection、Set、List接口都属于单值的操作,即:每次只能操作一个对象,而Map与它们不同的是,每次操作的是一对对象,即二元偶对象,Map中的每个元素都使用keyvalue的形式存储在集合之中,此接口定义如下:

·public interface Map<K,V>

Map接口中的方法

NO

方法或类

类型

描述

1

public void clear()

普通

清空Map集合

2

public boolean containsKey(Object key)

普通

判断指定的KEY是否存在

3

public boolean containsValue(Object value)

普通

判断指定的Value是否存在

4

public Set<Map.Entry<K,V>> entrySet()

普通

将Map对象变为Set集合

5

public Boolean equals(Object o)

普通

对象比较

6

public V get(Object key)

普通

根据key取得value

7

public int hashCode()

普通

返回哈希码

8

public boolean isEmpty()

普通

判断集合是否为空

9

public Set<K> keySet()

普通

取得所有的key

10

pubic V put(K key,V value)

普通

向集合中加入元素

11

public void putAll(Map<? extends K,? extends V> t)

普通

将一个Map集合中的内容加入到另一个Map

12

public V remove(Object key)

普通

根据key删除value

13

public int size()

普通

取出集合的长度

14

public Collection<V> values()

普通

取出全部的value

Map.Entry是Map中内部定义的一个接口,专门用来保存keyvalue的内容。Map.Entry接口定义:

·public static interface Map.Entry<K,V>

Map.Entry接口的常用方法

NO

方法或类

类型

描述

1

public boolean equals(Object o)

普通

对象比较

2

public K getKey()

普通

取得key

3

public V getValue()

普通

取得value

4

public int hashCode()

普通

返回哈希码

5

public V setValue(V value)

普通

设置value的值

JAVA学习基础之JAVA类集

Map接口的常用子类:

·HashMap:无序存放的,是新的操作类,key不允许重复

·Hashtable:无序存放的,是旧的操作类,key不允许重复

·TreeMap:可以排序的Map集合,按集合中的key排序,key不允许重复

·WeakHashMap:弱引用的Map集合,当集合中的某些内容不再使用时,可以清除掉无用的数据,可以使用gc进行回收

·IdentityHashMap:key可以重复的map集合

以HashMap为例,说明Map的基本方法操作:

import java.util.HashMap ;

import java.util.Map ;

public class HashMapDemo01{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new HashMap<String,String>() ;

map.put(“mldn”,”www.mldn.cn”) ; // 增加内容

map.put(“zhinangtuan”,”www.zhinangtuan.net.cn”) ; // 增加内容

map.put(“mldnjava”,”www.mldnjava.cn”) ; // 增加内容

String val = map.get(“mldn”) ; // 根据key取出值

System.out.println(“取出的内容是:” + val) ;

}

};

在map中也可以使用containsXxx()方法判断指定的key或者value是否存在。

import java.util.HashMap ;

import java.util.Map ;

public class HashMapDemo02{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new HashMap<String,String>() ;

map.put(“mldn”,”www.mldn.cn”) ; // 增加内容

map.put(“zhinangtuan”,”www.zhinangtuan.net.cn”) ; // 增加内容

map.put(“mldnjava”,”www.mldnjava.cn”) ; // 增加内容

if(map.containsKey(“mldn”)){ // 判断key是否存在

System.out.println(“搜索的key存在!”) ;

}else{

System.out.println(“搜索的key不存在!”) ;

}

if(map.containsValue(“www.mldn.cn”)){ // 判断value是否存在

System.out.println(“搜索的value存在!”) ;

}else{

System.out.println(“搜索的value不存在!”) ;

}

}

};

如果现在要输出全部的key,则使用如下方法:

·Set<K> keySet()

import java.util.HashMap ;

import java.util.Map ;

import java.util.Iterator ;

import java.util.Set ;

public class HashMapDemo03{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new HashMap<String,String>() ;

map.put(“mldn”,”www.mldn.cn”) ; // 增加内容

map.put(“zhinangtuan”,”www.zhinangtuan.net.cn”) ; // 增加内容

map.put(“mldnjava”,”www.mldnjava.cn”) ; // 增加内容

Set<String> keys = map.keySet() ; // 得到全部的key

Iterator<String> iter = keys.iterator() ;

while(iter.hasNext()){

String str = iter.next() ;

System.out.print(str + “、”) ;

}

}

};

既然可以输出全部的key,那么就肯定可以输出全部的value。

·Collection<V> values()

import java.util.HashMap ;

import java.util.Map ;

import java.util.Iterator ;

import java.util.Collection ;

public class HashMapDemo04{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new HashMap<String,String>() ;

map.put(“mldn”,”www.mldn.cn”) ; // 增加内容

map.put(“zhinangtuan”,”www.zhinangtuan.net.cn”) ; // 增加内容

map.put(“mldnjava”,”www.mldnjava.cn”) ; // 增加内容

Collection<String> values = map.values() ; // 得到全部的value

Iterator<String> iter = values.iterator() ;

while(iter.hasNext()){

String str = iter.next() ;

System.out.print(str + “、”) ;

}

}

};

在Map中也存在一个Hashtable子类,实际上这个子类的推出时间与Vector是一样的,都属于旧的类。

HashMap与Hashtable的区别

NO

比较点

HashMap

Hashtble

1

推出时间

JDK1.2之后推出,属于新的操作类

JDK1.0时推出,属于旧的操作类

2

性能

采用异步处理方式,性能更高

采用同步处理方式,性能较低

3

线程安全

属于非线程安全的操作类

属于线程安全的操作类

在Map中还存在一个TreeMap的子类,此类也属于排序类,按key排序。

import java.util.TreeMap ;

import java.util.Map ;

import java.util.Set ;

import java.util.Iterator ;

import java.util.Collection ;

public class TreeMapDemo01{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new TreeMap<String,String>() ;

map.put(“A、mldn”,”www.mldn.cn”) ; // 增加内容

map.put(“C、zhinangtuan”,”www.zhinangtuan.net.cn”) ; // 增加内容

map.put(“B、mldnjava”,”www.mldnjava.cn”) ; // 增加内容

Set<String> keys = map.keySet() ; // 得到全部的key

Iterator<String> iter = keys.iterator() ;

while(iter.hasNext()){

String str = iter.next() ;

System.out.println(str + ” –> ” + map.get(str)) ; // 取出内容

}

}

};

使用TreeMap可以方便的完成排序的操作。如果自定义的类要想做为key的话,则肯定要实现Comparable接口,指定比较的规则。

弱引用类:WeakHashMap

之前的Map子类中的数据都是使用强引用保存的,即:里面的内容不管是否使用都始终在集合中保留,如果希望集合可以自动清理暂时不用的数据就可以使用WeakHashMap类。WeakHashMap的定义如下:

·public class WeakHashMap<K,V>extends AbstractMap<K,V>implements Map<K,V>

如果假设一个Map中的某些内容长时间不使用的话,按照之前的做法是不会删除掉的,如果希望其可以自动删除掉,可以使用弱引用。当里面的某些内容不使用时,可以自动删除掉。

import java.util.WeakHashMap ;

import java.util.Map ;

import java.util.Set ;

import java.util.Iterator ;

import java.util.Collection ;

public class WeakHashMapDemo01{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new WeakHashMap<String,String>() ;

map.put(new String(“mldn”),new String(“www.mldn.cn”)) ;

map.put(new String(“zhinangtuan”),new String(“www.zhinangtuan.net.cn”)) ;

map.put(new String(“mldnjava”),new String(“www.mldnjava.cn”)) ;

System.gc() ; // 强制性进行垃圾的收集操作

map.put(new String(“cyg”),new String(“chenyegen”)) ;

System.out.println(map) ;

}

};

提示:对象的引用强度说明

从JDK1.2版本开始,JAVA把对象的引用分为四种级别,从而使程式能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:

·强引用:当内存不足时,JVM宁可出现OutOfMemeryError错误而使程序停止,也不会回收此对象来释放空间;

·软引用:当内存不足时,会回收这些对象的内存,用来实现内存敏感的高速缓存;

·弱引用:无论内存是否紧张,被垃圾回收器发现立即回收;

·虚引用:和没有任何引用一样。

13-11、JAVA类集—Map接口使用的注意事项

Map接口输出:

对于Map接口来说,其本身是不能直接使用迭代(例如:Iterator、foreach)进行输出的,因为Map中的每个位置存放的是一对值(keyvalue),而Iterator中每次只能找到一个值,所以,如果此时非要使用迭代进行输出的话,则必须按照以下的步骤完成(以Iterator输出方法为例):

·1、将Map的实例通过entrySet()方法变为Set接口对象;

·2、通过Set接口实例为Iterator实例化;

·3、通过Iterator迭代输出,每个内容都是Map.Entry的对象;

·4、通过Map.Entry进行keyvalue的分离。

但是在操作前必须说明的是:Map接口一般只作为查找使用,输出的操作毕竟属于少数。

import java.util.HashMap ;

import java.util.Map ;

import java.util.Set ;

import java.util.Iterator ;

public class IteratorDemo04{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new HashMap<String,String>() ;

map.put(“mldn”,”www.mldn.cn”) ; // 增加内容

map.put(“zhinangtuan”,”www.zhinangtuan.net.cn”) ; // 增加内容

map.put(“mldnjava”,”www.mldnjava.cn”) ; // 增加内容

Set<Map.Entry<String,String>> allSet = null ;

allSet = map.entrySet() ;

Iterator<Map.Entry<String,String>> iter = null ;

iter = allSet.iterator() ;

while(iter.hasNext()){

Map.Entry<String,String> me = iter.next() ;

System.out.println(me.getKey() + ” –> ” + me.getValue()) ;

}

}

};

第一种方式,使用Iterator完成。当然在JDK1.5之后也可以使用foreach完成。

import java.util.HashMap ;

import java.util.Map ;

import java.util.Set ;

import java.util.Iterator ;

public class ForeachDemo02{

public static void main(String args[]){

Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String

map = new HashMap<String,String>() ;

map.put(“mldn”,”www.mldn.cn”) ; // 增加内容

map.put(“zhinangtuan”,”www.zhinangtuan.net.cn”) ; // 增加内容

map.put(“mldnjava”,”www.mldnjava.cn”) ; // 增加内容

for(Map.Entry<String,String> me:map.entrySet()){

System.out.println(me.getKey() + ” –> ” + me.getValue()) ;

}

}

};

这两种输出形式最终实际上还是以Collection的形式输出,只是以Map.Entry作为内容的操作类型。

在MAP中,可以使用任意类型作为key和value,那么使用非系统类也可以。

import java.util.Map ;

import java.util.HashMap ;

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 HashMapDemo05{

public static void main(String args[]){

Map<String,Person> map = null ;

map = new HashMap<String,Person>() ;

map.put(“zhangsan”,new Person(“张三”,30)); // 增加内容

System.out.println(map.get(“zhangsan”)) ;

}

};

如果现在以String为key是可以取出内容的。

import java.util.Map ;

import java.util.HashMap ;

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 HashMapDemo06{

public static void main(String args[]){

Map<Person,String> map = null ;

map = new HashMap<Person,String>() ;

map.put(new Person(“张三”,30),”zhangsan”); // 增加内容

System.out.println(map.get(new Person(“张三”,30))) ;

}

};

此时,只是将自定义的类作为key,但是在取值的时候发现取不了了,返回的结果是null,那么为什么之前的String可以,但是自定义的类不存在呢?

实际上,对于匹配过程来讲,有一个特点,即:对象要一样才可以将内容查询出来。

import java.util.Map ;

import java.util.HashMap ;

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 HashMapDemo07{

public static void main(String args[]){

Map<Person,String> map = null ;

map = new HashMap<Person,String>() ;

Person per = new Person(“张三”,30) ;

map.put(per,”zhangsan”); // 增加内容

System.out.println(map.get(per)) ;

}

};

可是这样并不是解决问题的方法,因为不可能将Person的per对象到处带着走啊,应该像String一样,可以使用匿名对象的形式找到内容。那么此时,实际上就需要按照与Set接口中判断重复元素的方式一样,进行方法的覆写。

  • 注意事项二:直接使用非系统类作为key

如果要使用非系统类作为Map的key,则此类必须覆写Object类中的以下两个方法:

·hashCode()

·equals

import java.util.Map ;

import java.util.HashMap ;

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(){

return this.name.hashCode() * this.age ;

}

};

public class HashMapDemo08{

public static void main(String args[]){

Map<Person,String> map = null ;

map = new HashMap<Person,String>() ;

map.put(new Person(“张三”,30),”zhangsan”); // 增加内容

System.out.println(map.get(new Person(“张三”,30))) ;

}

};

作为key,或者更准确的说是作为对象的时候,实际上是依靠hashCode()和equals()判断两个匿名对象是否相等,这一点由系统内部自动完成。

总结:

1、Map可以使用迭代输出

·mapentrySetSetIteratorMap.Entrykey和value

2、如果使用非系统类作为key,则一定保证覆写equals和hashCode()方法,否则无效。

13-12、JAVA类集—IdentityHashMap类

在正常的Map操作中,key本身是不能够重复的:

import java.util.IdentityHashMap ;

import java.util.HashMap ;

import java.util.Set ;

import java.util.Iterator ;

import java.util.Map ;

class Person{

private String name ;

private int age ;

public Person(String name,int age){

this.name = name ;

this.age = 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(){

return this.name.hashCode() * this.age ;

}

public String toString(){

return “姓名:” + this.name + “,年龄:” + this.age ;

}

};

public class IdentityHashMapDemo01{

public static void main(String args[]){

Map<Person,String> map = null ; // 声明Map对象

map = new HashMap<Person,String>() ;

map.put(new Person(“张三”,30),”zhangsan_1″) ; // 加入内容

map.put(new Person(“张三”,30),”zhangsan_2″) ; // 加入内容

map.put(new Person(“李四”,31),”lisi”) ; // 加入内容

Set<Map.Entry<Person,String>> allSet = null ; // 准备使用Set接收全部内容

allSet = map.entrySet() ;

Iterator<Map.Entry<Person,String>> iter = null ;

iter = allSet.iterator() ;

while(iter.hasNext()){

Map.Entry<Person,String> me = iter.next() ;

System.out.println(me.getKey() + ” –> ” + me.getValue()) ;

}

}

};

使用HashMap操作的时候,key内容是不能重复的,如果现在希望key的内容可以重复(这里的重复是指两个对象的地址不一样key1= =key2)则要使用IdentityHashMap类。

import java.util.IdentityHashMap ;

import java.util.Set ;

import java.util.Iterator ;

import java.util.Map ;

class Person{

private String name ;

private int age ;

public Person(String name,int age){

this.name = name ;

this.age = 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(){

return this.name.hashCode() * this.age ;

}

public String toString(){

return “姓名:” + this.name + “,年龄:” + this.age ;

}

};

public class IdentityHashMapDemo02{

public static void main(String args[]){

Map<Person,String> map = null ; // 声明Map对象

map = new IdentityHashMap<Person,String>() ;

map.put(new Person(“张三”,30),”zhangsan_1″) ; // 加入内容

map.put(new Person(“张三”,30),”zhangsan_2″) ; // 加入内容

map.put(new Person(“李四”,31),”lisi”) ; // 加入内容

Set<Map.Entry<Person,String>> allSet = null ; // 准备使用Set接收全部内容

allSet = map.entrySet() ;

Iterator<Map.Entry<Person,String>> iter = null ;

iter = allSet.iterator() ;

while(iter.hasNext()){

Map.Entry<Person,String> me = iter.next() ;

System.out.println(me.getKey() + ” –> ” + me.getValue()) ;

}

}

};

就算是两个对象的内容相等,但是因为都使用了new关键字,所以地址肯定不等,那么就可以加入进去,key是可以重复的。

总结:

了解IdentityHashMap类的作用即可,在实际中此类使用的非常少。

13-13、JAVA类集—SortedMap接口

回顾:SortedSet,是TreeSet的实现接口,那么此接口可以进行排序的操作。

SortedMap也是排序的操作,之前学习过TreeMap类,那么此类是可以排序的。

SortedMap接口扩展的方法

NO

方法

类型

描述

1

public Comparator<? Super K> comparator()

普通

返回比较器对象

2

public K firstKey()

普通

返回第一个元素的key

3

public SortedMap<K,V>headMap(K toKey)

普通

返回小于等于指定key的部分集合

4

public K lastKey()

普通

返回厚后一个元素的key

5

public SortedMap<K,V> subMap(K fromKey,K toKey)

普通

返回指定key范围的集合

6

public SortedMap<K,V> tailMap(K fromKey)

普通

返回大于指定key的部分集合

范例:

import java.util.Map ;

import java.util.SortedMap ;

import java.util.TreeMap ;

public class SortedMapDemo{

public static void main(String args[]){

SortedMap<String,String> map = null ;

map = new TreeMap<String,String>() ; // 通过子类实例化接口对象

map.put(“D、jiangker”,”#34;) ;

map.put(“A、mldn”,”www.mldn.cn”) ;

map.put(“C、zhinangtuan”,”www.zhinangtuan.net.cn”) ;

map.put(“B、mldnjava”,”www.mldnjava.cn”) ;

System.out.print(“第一个元素的内容的key:” + map.firstKey()) ;

System.out.println(“:对应的值:” + map.get(map.firstKey())) ;

System.out.print(“最后一个元素的内容的key:” + map.lastKey()) ;

System.out.println(“:对应的值:” + map.get(map.lastKey())) ;

System.out.println(“返回小于指定范围的集合:”) ;

for(Map.Entry<String,String> me:map.headMap(“B、mldnjava”).entrySet()){

System.out.println(“t|- ” + me.getKey() + ” –> ” + me.getValue()) ;

}

System.out.println(“返回大于指定范围的集合:”) ;

for(Map.Entry<String,String> me:map.tailMap(“B、mldnjava”).entrySet()){

System.out.println(“t|- ” + me.getKey() + ” –> ” + me.getValue()) ;

}

System.out.println(“部分集合:”) ;

for(Map.Entry<String,String> me:map.subMap(“A、mldn”,”C、zhinangtuan”).entrySet()){

System.out.println(“t|- ” + me.getKey() + ” –> ” + me.getValue()) ;

}

}

};

13-14、JAVA类集—集合工具类:Collections

Collections类与Collection没有直接关系,但是与集合中的各个接口都有操作的方法支持。

Collections类的常用方法及常量

NO

方法

类型

描述

1

public static final List EMPTY_LIST

常量

返回一个空的List集合

2

public static final Set EMPTY_SET

常量

返回空的Set集合

3

public static final Map EMPTY_MAP

常量

返回空的Map集合

4

public static <T> boolean addAll(Collection<? super T> c,T…a)

普通

为集合添加内容

5

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

普通

找到最大的内容,按比较器排序

6

public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)

普通

找到集合中的最小内容,按比较器排序

7

public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal)

普通

用新的内容替换集合的指定内容

8

public static void reverse(List<?> list)

普通

集合反转

9

public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key)

普通

查找集合中的指定内容

10

public static final<T> List<T> emptyList()

普通

返回一个空的List集合

11

public static final<K,V> Map<K,V> emptyMap()

普通

返回一个空的Map集合

12

public static final<T> Set<T> emptySet()

普通

返回一个空的Set集合

13

public static <T extends Comparable<? super T>> void sort(List<T> list)

普通

集合排序操作,根据Comparable接口进行排序

14

public static void swap(List<?> list,int i,int j)

普通

交换指定位置的元素

验证,空集合的操作:

·public static final <T> List<T> emptyList()

·public static final <T> Set<T> emptySet()

import java.util.Collections ;

import java.util.List ;

import java.util.Set ;

public class CollectionsDemo01{

public static void main(String args[]){

List<String> allList = Collections.emptyList() ; // 返回空的 List集合

Set<String> allSet = Collections.emptySet() ; // 返回空的 List集合

allList.add(“Hello”) ; // 加入数据

}

};

如果要想为集合中增加内容,则肯定使用add()方法,在Collections中也提供了专门的增加操作。

public static <T> Boolean addAll(Collection<? super T> c,T…elements)

使用了可变参数,所以可以任意输入各种类型的数据。

import java.util.Collections ;

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class CollectionsDemo02{

public static void main(String args[]){

List<String> all = new ArrayList<String>() ; // 返回空的 List集合

Collections.addAll(all,”MLDN”,”LXH”,”mldnjava”) ;

Iterator<String> iter = all.iterator() ;

while(iter.hasNext()){

System.out.print(iter.next() + “、”) ;

}

}

};

选择何种的加入操作根据个人喜好。

内容反转操作:

import java.util.Collections ;

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class CollectionsDemo03{

public static void main(String args[]){

List<String> all = new ArrayList<String>() ; // 返回空的 List集合

Collections.addAll(all,”MLDN”,”LXH”,”mldnjava”) ;

Collections.reverse(all) ; // 内容反转

Iterator<String> iter = all.iterator() ;

while(iter.hasNext()){

System.out.print(iter.next() + “、”) ;

}

}

};

在Collections中也提供了二分检索的方法:

public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key)

完成检索:

import java.util.Collections ;

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class CollectionsDemo04{

public static void main(String args[]){

List<String> all = new ArrayList<String>() ; // 返回空的 List集合

Collections.addAll(all,”MLDN”,”LXH”,”mldnjava”) ;

int point = Collections.binarySearch(all,”LXH”) ; // 检索数据

System.out.println(“检索结果:” + point) ;

}

};

替换内容:

public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal)

执行替换操作:

import java.util.Collections ;

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class CollectionsDemo05{

public static void main(String args[]){

List<String> all = new ArrayList<String>() ; // 返回空的 List集合

Collections.addAll(all,”MLDN”,”LXH”,”mldnjava”) ;

if(Collections.replaceAll(all,”LXH”,”李兴华”)){// 替换内容

System.out.println(“内容替换成功!”) ;

}

System.out.print(“替换之后的结果:”) ;

System.out.print(all) ;

}

};

之前曾经说过,使用TreeSet可以进行排序操作,那么在Colletions类中也提供了这样的一个排序操作:

public static <T extends Comparable<? super T>> void sort(List<T> list)

实现排序功能:

import java.util.Collections ;

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class CollectionsDemo06{

public static void main(String args[]){

List<String> all = new ArrayList<String>() ; // 返回空的 List集合

Collections.addAll(all,”1、MLDN”,”2、LXH”,”3、mldnjava”) ;

Collections.addAll(all,”B、www.mldn.cn”) ;

Collections.addAll(all,”A、www.mldnjava.cn”) ;

System.out.println(“排序之前的集合:” + all) ;

Collections.sort(all) ;

System.out.println(“排序之后的集合:” + all) ;

}

};

如果要进行排序的话,是肯定对象所在的类必须实现Comparable接口。

交换指定位置的内容:

public static void swap(List<?> list,int i,int j)

完成一个交换内容的操作:

import java.util.Collections ;

import java.util.List ;

import java.util.ArrayList ;

import java.util.Iterator ;

public class CollectionsDemo07{

public static void main(String args[]){

List<String> all = new ArrayList<String>() ; // 返回空的 List集合

Collections.addAll(all,”1、MLDN”,”2、LXH”,”3、mldnjava”) ;

System.out.println(“交换之前的集合:” + all) ;

Collections.swap(all,0,2) ;

System.out.println(“交换之后的集合:” + all) ;

}

};

总结:

1、在类集中为了方便集合的操作,提供了Collections类,此类与Collection接口没有直接的继承或实现关系,只是对所有的接口有所支持而已;

2、开发中是否使用此类没有明确的规定,按照个人的喜好执行即可。

13-15、JAVA类集—Stack类

栈是采用先进后出的数据存储方式,每一个栈都包含一个栈顶,每次出栈是将栈顶的数据取出:

JAVA学习基础之JAVA类集

在JAVA中使用Stack类进行栈的操作,Stack类是Vector的子类,Stack的定义如下:

·public class Stack<E> extends Vector<E>

Stack类的常用方法

NO

方法

类型

描述

1

public boolean empty()

常量

测试栈是否为空

2

public E peek()

常量

查看栈顶,但不删除

3

public E pop()

常量

出栈,同时删除

4

public E push(E item)

普通

入栈

5

public int search(Object o)

普通

在栈中查找

是Vector的一个子类。

import java.util.Stack ;

public class StackDemo{

public static void main(String args[]){

Stack<String> s = new Stack<String>() ;

s.push(“A”) ; // 入栈

s.push(“B”) ; // 入栈

s.push(“C”) ; // 入栈

System.out.print(s.pop() + “、”) ;

System.out.print(s.pop() + “、”) ;

System.out.println(s.pop() + “、”) ;

System.out.println(s.pop()) ;

}

};

如果栈中已经没有内容了,则无法继续出栈。

13-16、JAVA类集—属性类:Properties

属性是在程序中经常出现的一种形式。

在类集中提供了一个专门的Properties类,以完成属性的操作。

public class Properties extends Hashtable<Object,Object>

Properties是Hashtable的子类,则也是Map的子类,可以使用Map的全部操作,但是一般情况下属性类是单独使用的。

设置和取得属性:

设置属性:

public Object setProperty(String key,String value)

得到属性:

public String getProperty(String key)

public String getProperty(String key,String defaultValue)

验证以上操作:

import java.util.Properties;

public class PropertiesDemo01{

public static void main(String args[]){

Properties pro = new Properties() ; // 创建Properties对象

pro.setProperty(“BJ”,”BeiJing”) ; // 设置属性

pro.setProperty(“TJ”,”TianJin”) ;

pro.setProperty(“NJ”,”NanJing”) ;

System.out.println(“1、BJ属性存在:” + pro.getProperty(“BJ”)) ;

System.out.println(“2、SC属性不存在:” + pro.getProperty(“SC”)) ;

System.out.println(“3、SC属性不存在,同时设置显示的默认值:” + pro.getProperty(“SC”,”没有发现”)) ;

}

};

属性操作中以上属于设置和读取属性,当然,对于属性中也可以将属性保存在文件之中。提供了以下的方法:

public void store(OutputStream out,String comments) throws IOException

将以上的属性写入到d:area.properties文件中。

import java.util.Properties;

import java.io.File;

import java.io.FileOutputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

public class PropertiesDemo02{

public static void main(String args[]){

Properties pro = new Properties() ; // 创建Properties对象

pro.setProperty(“BJ”,”BeiJing”) ; // 设置属性

pro.setProperty(“TJ”,”TianJin”) ;

pro.setProperty(“NJ”,”NanJing”) ;

File file = new File(“D:” + File.separator + “area.properteis”) ; // 指定要操作的文件

try{

pro.store(new FileOutputStream(file),”Area Info”) ; // 保存属性到普通文件

}catch(FileNotFoundException e){

e.printStackTrace() ;

}catch(IOException e){

e.printStackTrace() ;

}

}

};

此时已经将属性内容保存在了文件之中,既然可以保存,那么就可以读取。

public void load(InputStream inStream) throws IOException

使用以上方法读取属性内容。

import java.util.Properties;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

public class PropertiesDemo03{

public static void main(String args[]){

Properties pro = new Properties() ; // 创建Properties对象

File file = new File(“D:” + File.separator + “area.properteis”) ; // 指定要操作的文件

try{

pro.load(new FileInputStream(file)) ; // 读取属性文件

}catch(FileNotFoundException e){

e.printStackTrace() ;

}catch(IOException e){

e.printStackTrace() ;

}

System.out.println(“1、BJ属性存在:” + pro.getProperty(“BJ”)) ;

System.out.println(“2、SH属性存在:” + pro.getProperty(“SH”)) ;

}

};

以上是全部保存在了普通的文件之中,实际上在Properties操作的时候也可以将内容全部保存在XML文件之中。

import java.util.Properties;

import java.io.File;

import java.io.FileOutputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

public class PropertiesDemo04{

public static void main(String args[]){

Properties pro = new Properties() ; // 创建Properties对象

pro.setProperty(“BJ”,”BeiJing”) ; // 设置属性

pro.setProperty(“TJ”,”TianJin”) ;

pro.setProperty(“NJ”,”NanJing”) ;

File file = new File(“D:” + File.separator + “area.xml”) ; // 指定要操作的文件

try{

pro.storeToXML(new FileOutputStream(file),”Area Info”) ; // 保存属性到普通文件

}catch(FileNotFoundException e){

e.printStackTrace() ;

}catch(IOException e){

e.printStackTrace() ;

}

}

};

既然可以使用XML文件格式保存,那么就可以使用XML文件读取内容。

import java.util.Properties;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

public class PropertiesDemo05{

public static void main(String args[]){

Properties pro = new Properties() ; // 创建Properties对象

File file = new File(“D:” + File.separator + “area.xml”) ; // 指定要操作的文件

try{

pro.loadFromXML(new FileInputStream(file)) ; // 读取属性文件

}catch(FileNotFoundException e){

e.printStackTrace() ;

}catch(IOException e){

e.printStackTrace() ;

}

System.out.println(“1、BJ属性存在:” + pro.getProperty(“BJ”)) ;

}

};

总结:

1、如果要进一步了解属性操作,则可以继续学习后续的反射机制部分,了解属性类的应用。

2、属性中的类型肯定都是字符串,因为操作最方便。

3、属性可以向普通文件或XML文件中保存或读取,按照指定格式可以向文件中任意扩充属性。

13-17、JAVA类集—范例(一):一对多关系

实例要求:

使用类集可以表示出以下的关系:一个学校可以包含多个学生,一个学生属于一个学校,那么这就是一个典型的一对多关系,此时就可以通过类集进行关系的表示。

一个学校有多个学生,那么学生的个数属于未知的,这样一来肯定无法用普通的对象数组表示,必须通过类集表示。

学生类:

public class Student{

private String name ;

private int age ;

private School school; // 一个学生属于一个学校

public Student(String name,int age){

this.setName(name) ;

this.setAge(age) ;

}

public void setSchool(School school){

this.school = school ;

}

public School getSchool(){

return this.school ;

}

public void setName(String name){

this.name = name ;

}

public void setAge(int age){

this.age = age ;

}

public String getName(){

return this.name;

}

public int getAge(){

return this.age ;

}

public String toString(){

return “学生姓名:” + this.name + “;年龄:” + this.age ;

}

};

学校类:

import java.util.List ;

import java.util.ArrayList ;

public class School{

private String name ;

private List<Student> allStudents ;

public School(){

this.allStudents = new ArrayList<Student>() ;

}

public School(String name){

this() ;

this.setName(name) ;

}

public void setName(String name){

this.name = name ;

}

public String getName(){

return this.name;

}

public List<Student> getAllStudents(){

return this.allStudents ;

}

public String toString(){

return “学校名称:” + this.name ;

}

};

主类:

import java.util.Iterator ;

public class TestDemo{

public static void main(String args[]){

School sch = new School(“清华大学”) ; // 定义学校

Student s1 = new Student(“张三”,21) ;

Student s2 = new Student(“李四”,22) ;

Student s3 = new Student(“王五”,23) ;

sch.getAllStudents().add(s1) ;

sch.getAllStudents().add(s2) ;

sch.getAllStudents().add(s3) ;

s1.setSchool(sch) ;

s2.setSchool(sch) ;

s3.setSchool(sch) ;

System.out.println(sch) ;

Iterator<Student> iter = sch.getAllStudents().iterator() ;

while(iter.hasNext()){

System.out.println(“t|- ” + iter.next()) ;

}

}

};

总结:

明白类集的关系,这种关系将成为日后标准程序的开发基础。

13-18、JAVA类集—范例(二):多对多关系

实例要求:

·一个学生可以选多门课程,一门课程可以有多个学生参加,那么这就是个典型的多对多关系。

·要完成本程序,首先应该定义两个类:学生信息类Student、课程信息类Course,在一个学生类中存在一个集合,保存全部的课程,而在课程类中也要存在一个集合,保存全部的学生。

学生类:

import java.util.List ;

import java.util.ArrayList ;

public class Student{

private String name ;

private int age ;

private List<Course> allCourses ;

public Student(){

this.allCourses = new ArrayList<Course>() ;

}

public Student(String name,int age){

this() ;

this.name = name ;

this.age = age ;

}

public List<Course> getAllCourses(){

return this.allCourses ;

}

public void setName(String name){

this.name = name ;

}

public void setAge(int age){

this.age = age ;

}

public String getName(){

return this.name ;

}

public int getAge(){

return this.age ;

}

public String toString(){

return “学生姓名:” + this.name + “;年龄:” + this.age ;

}

};

课程成绩类:

import java.util.List ;

import java.util.ArrayList ;

public class Course{

private String name ;

private int credit ;

private List<Student> allStudents ;

public Course(){

this.allStudents = new ArrayList<Student>() ;

}

public Course(String name,int credit){

this() ;

this.name = name ;

this.credit = credit ;

}

public List<Student> getAllStudents(){

return this.allStudents ;

}

public void setName(String name){

this.name = name ;

}

public void setCredit(int credit){

this.credit = credit ;

}

public String getName(){

return this.name ;

}

public int getCredit(){

return this.credit ;

}

public String toString(){

return “课程名称:” + this.name + “;课程学分:” + this.credit ;

}

};

主类:

import java.util.Iterator ;

public class TestMore{

public static void main(String args[]){

Course c1 = new Course(“英语”,3 ) ; // 第一门课程

Course c2 = new Course(“计算机”,5) ; // 第二门课程

Student s1 = new Student(“张三”,20) ;

Student s2 = new Student(“李四”,21) ;

Student s3 = new Student(“王五”,22) ;

Student s4 = new Student(“赵六”,23) ;

Student s5 = new Student(“孙七”,24) ;

Student s6 = new Student(“钱八”,24) ;

// 第一门课程有三个学生参加

c1.getAllStudents().add(s1) ;

c1.getAllStudents().add(s2) ;

c1.getAllStudents().add(s6) ;

s1.getAllCourses().add(c1) ;

s2.getAllCourses().add(c1) ;

s6.getAllCourses().add(c1) ;

// 第二门课程有六个学生参加

c2.getAllStudents().add(s1) ;

c2.getAllStudents().add(s2) ;

c2.getAllStudents().add(s3) ;

c2.getAllStudents().add(s4) ;

c2.getAllStudents().add(s5) ;

c2.getAllStudents().add(s6) ;

s1.getAllCourses().add(c2) ;

s2.getAllCourses().add(c2) ;

s3.getAllCourses().add(c2) ;

s4.getAllCourses().add(c2) ;

s5.getAllCourses().add(c2) ;

s6.getAllCourses().add(c2) ;

// 输出一门课程的信息,观察一门课程有多少个学生参加

System.out.println(c1) ;

Iterator<Student> iter1 = c1.getAllStudents().iterator() ;

while(iter1.hasNext()){

Student s = iter1.next() ;

System.out.println(“t|- ” + s) ;

}

// 通过学生找到学生参加的课程

System.out.println(s6) ;

Iterator<Course> iter2 = s6.getAllCourses().iterator() ;

while(iter2.hasNext()){

Course c = iter2.next() ;

System.out.println(“t|- ” + c) ;

}

}

};

文章来源:智云一二三科技

文章标题:JAVA学习基础之JAVA类集

文章地址:https://www.zhihuclub.com/183433.shtml

关于作者: 智云科技

热门文章

网站地图