您的位置:首页 > 编程语言 > Java开发

Java类集笔记

2016-04-07 21:06 369 查看
在学习完Java类集之后,对于这部分知识希望有一个小结。类集,实际上就是一个动态的对象数组,通常在java.util这个包中,通过API文档很容易查阅到。对象数组中包含一组对象,对象数组使用有长度的限制,类集就是解决这种限制。在Java中常用的集合接口有Collection<E>和Map<K,V>,Collection接口的经常用到子接口有List<E>,Set<E>,Map接口的常用子类有HashMap,LinkedHashMap,TreeMap。下面就对这两个常用的接口以及子接口和子类做一些介绍。

Collection<E>

public interfaceCollection<E>extendsIterable<E>

对于Iterable<E>这个接口之后会介绍到,先说Collection<E>这个接口,它有两个常用的子接口List<E>,Set<E>,常用操作add()加入元素,remove()移除元素,clear()清空所有元素,iterator()访问

List<E>

public interfaceList<E>extendsCollection<E>

在List中可以存放任意的数据,内容可以重复,同时也是有序的,List这个接口也有继承自己的子类:ArrayList, LinkedList, Vector

ArrayList<E>

以下是对这个子类的操作,从List这个接口中来的,它是以数组的方式实现的,读取速度快,适合随机访问。

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("A") ;	                // 向Collection中加入内容
allCollection.add("B") ;
allList.addAll(allCollection) ;
allList.addAll(0,allCollection) ;
System.out.println(allList) ;
}
};
以上是向ArrayList中加入元素,运行结果:

[World, Hello]

[A, B, World, Hello, A, B]

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
allList.add("Hello") ;                	// 此方法由Collection接口而来
allList.add(0,"World") ;	        // 在第一个位置上添加新的内容
allList.add("A") ;	                // 向Collection中加入内容
allList.add("B") ;
allList.remove(0) ;                     // 删除第一个元素,指定删除的位置
allList.remove("Hello") ;	        // 此方法由Collection接口继承而来
System.out.println(allList) ;
}
};
删除元素,运行结果:[A, B]

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
allList.add("Hello") ;	                // 此方法由Collection接口而来
allList.add("Hello") ;	                // 此方法由Collection接口而来
allList.add(0,"World") ;	        // 在第一个位置上添加新的内容
allList.add("A") ;
allList.add("B") ;
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) + "、") ;
}
}
};
运行结果:

由前向后输出:World、Hello、Hello、A、B、

由后向前输出:B、A、Hello、Hello、World、

这里也可以将ArrayList中的元素转化成数组的形式在输出,如:

String str[] = (String[])allList.toArray() ;	        // 指定好类型
String str[] = allList.toArray(new String[]{}) ;	// 指定好类型
在这里说一下Vector这个子类,它的一些操作与ArrayList是一样的,但是又有一些区别;

ArrayList 采用异步的方式处理,性能高,非线程安全操作类,只能用Iterator foreach 输出

Vector 同步的方式处理,性能较低,属于线程安全操作类,可以用Iterator foreach Enumeration输出

LinkedList<E>

采用双向链表实现集合,对于删除插入操作比较快,读取速度慢

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) ;
}
};
一些基本的插入操作,运行结果:

初始化链表:[A, B, C]

增加头和尾之后的链表:[X, A, B, C, Y]

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) ;

}
};
注意找到表中元素各个方法之间的不同,运行结果:

1-1、element()方法找到表头:A

1-2、找完之后的链表的内容:[A, B, C]

2-1、peek()方法找到表头:A

2-2、找完之后的链表的内容:[A, B, C]

3-1、poll()方法找到表头:A

3-2、找完之后的链表的内容:[B, C]

element()与peek()不同的是,element()在表为空是会抛出异常:
NoSuchElementException,而peek()会返回null。


Set<E>

public interface Set<E>extends Collection<E>


Set接口也是Collection的接口,但是不允许加入重复元素,它也有常用子类HashSet,TreeSet

Hashset<E>

不能加入重复元素,同时其中的元素输出是无序的(LinkedSet是以链表实现HashSet,保留元素的插入顺序,在此不做过多介绍),对于重复元素的消除需要用到Object类中的两个方法,hashcode(),equals()进行比较

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) ;
}
};
运行结果:[A, B, C, D, E] ;其中重复元素C已经只有一个。在看下面例子:
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 HashSetDemo02{
public static void main(String args[]){
Set<Person> allSet = new HashSet<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) ;
}
};
运行结果;

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

会发现这里没有去除相同的对象,所以需要Object类中的两个方法hashcode(),equals();而之前加入的对象是String类,其中已经覆写了这两个方法。

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("李四",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) ;
}
};
运行结果:[姓名:赵六;年龄:33, 姓名:王五;年龄:32, 姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:孙七;年龄:33]

TreeSet<E>

不能加入重复元素,同时其中的元素是可以排序的,对于排序比较时会用到Comparable接口中的compareTo()方法来对元素进行比较。

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) ;
}
};
运行结果:[A, B, C, D, E] 消除了相同的元素,同时对元素进行了排序
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){     //元素之间的比较需要覆写此方法,且返回1表示大于,-1表示小于,0表示等于,也可以自己定义排序规则
if(this.age>per.age){
return 1 ;
}else if(this.age<per.age){
return -1 ;
}else{
return 0 ;
}
}
};
public class TreeSetDemo01{
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) ;
}
};
运行结果:[姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32, 姓名:赵六;年龄:33] ;如果该类没有实现Comparable接口,覆写其compareTo()方法,则会报错抛出异常,而String类中已经实现了,所以可以直接用,这个类排序规则是按年龄排序的,会发现孙七没有出现,因为排序规则中只对年龄做了处理。这个时候如果需要打印出孙七则需要对所有属性进行比较,可以在compareTo()中加入对姓名的比较,直接用String类中的这个方法就可以了,代码修改如下
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()方法
}
}


Map<K,E>

Map<K,E>是以键/值对的形式存放数据,它有一些常用的子类,HashMap,TreeMap这两个子类中Key值是不可以重复的;

HashMap<K,E>

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("A","a") ;
map.put("B","b") ;
map.put("C","c") ;
String val = map.get("B") ;	   // 根据key取出值
System.out.println("取出的内容是:" + val) ;
if(map.containsKey("A")){	   // 判断key是否存在
System.out.println("搜索的key存在!") ;
}else{
System.out.println("搜索的key不存在!") ;
}
if(map.containsValue("D")){	// 判断value是否存在
System.out.println("搜索的value存在!") ;
}else{
System.out.println("搜索的value不存在!") ;
}
}
};
运行结果:

取出的内容是:b

搜索的key存在!

搜索的value不存在!

在Map中加入数据时用put()方法,还有remove()移除一个元素,clear()清除等方法,containsKey(),containsValue()这个两个方法是根据键值映射值键,返回值为boolean型。接下来对输出做简单的介绍(毕竟查找才是map接口的主要作用),输出所有的key值,所有的vaule值:

import java.util.HashMap ;
import java.util.Map ;
import java.util.Iterator ;
import java.util.Set ;
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("A","a") ;	// 增加内容
map.put("B","b") ;	// 增加内容
map.put("C","c") ;	// 增加内容
Set<String> keys = map.keySet() ;	// 得到全部的key
Iterator<String> iter = keys.iterator() ;
while(iter.hasNext()){
String str = iter.next() ;
System.out.print(str + "、") ;
}
}
};
运行结果:A、B、C、
import java.util.HashMap ;
import java.util.Map ;
import java.util.Iterator ;
import java.util.Collection ;
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("A","a") ;	// 增加内容
map.put("B","b") ;	// 增加内容
map.put("C","c") ;	// 增加内容
Collection<String> values = map.values() ;	// 得到全部的value
Iterator<String> iter = values.iterator() ;
while(iter.hasNext()){
String str = iter.next() ;
System.out.print(str + "、") ;
}
}
};
运行结果:a、b、c、

输出所有key时用到了Set<K> keySet()这个方法,而输出所有的value时用Collction<K> values(),其实可以想到,Key值的唯一性是的在向上转型只能用Set接收。

TreeSet<K,E>

import java.util.TreeMap ;
import java.util.Map ;
import java.util.Set ;
import java.util.Iterator ;
import java.util.Collection ;
public class HashMapDemo01{
public static void main(String args[]){
Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String
map = new TreeMap<String,String>() ;
map.put("A","a") ;
map.put("C","b") ;
map.put("B","c") ;
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)) ; // 取出内容
}
}
};
运行结果;

A --> a

B --> c

C --> b

TreeMap属于排序类,按照key值进行排序。Map中还有一个HashTable子类,是一个旧类,其操作与HashMap类似,也有些区别(这个在面试中经常会问的)

HashTable HashMap:( 这部分知识网上很多,以下摘录)

(1)HashTable是同步的处理方式,线程安全,而HashMap是异步的处理方式性能高,线程不安全(有没有发现ArrayList与Vector,StringBuffer与StringBuilder都类似)

(2)HashTable不容许有null值(key和value都不行),而HashMap容许有null值(key和value都行);

(3)哈希值的使用不同,HashTable直接使用对像的hashCode,而HashMap会重新计算hash值。

(4)HashTable使用Enumeration遍历,而HashMap使用Iterator遍历。

上面的输出方式使用到了Iterator完成的,当然也有其他的输出方式,需要用到Map中的内部接口Map.Entry<K,E>

import java.util.HashMap ;
import java.util.Map ;
import java.util.Set ;
import java.util.Iterator ;
public class ForeachDemo01{
public static void main(String args[]){
Map<String,String> map = null; // 声明Map对象,其中key和value的类型为String
map = new HashMap<String,String>() ;
map.put("A","a") ;
map.put("B","b") ;
map.put("C","c") ;
for(Map.Entry<String,String> me:map.entrySet()){
System.out.println(me.getKey() + " --> " + me.getValue()) ;
}
}
};


运行结果:

A --> a

B --> b

C --> c

Map.Entry<K,E>中存放Map的键值对,通过getKey()方法和getValue()方法得到,以上是通过foreach的方式输出。如果是自定义类作为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 ForeachDemo01{
public static void main(String args[]){
Map<Person,String> map = null ;
map = new HashMap<Person,String>() ;
map.put(new Person("张三",30),"zhangsan");	//匿名方式实例作为key
System.out.println(map.get(new Person("张三",30))) ;
}
};
运行结果:null ;结果输出为空!!对象需要一样才能有效查询,两个实例化其实所指对象是不同的。可以将后几句改为
Person per = new Person("张三",30) ;
map.put(per,"zhangsan");
System.out.println(map.get(per)) ;
这样的话运行结果就是 zhangsan。但是这样做却不得不每次都要显示的实例化,这样做会很麻烦,这时就需要跟Set接口判断重复元素一样覆写Object类中的两个方法:
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 ;
}

在上例类中需要覆写以上两个方法。最后对开始提到的Iterator接口简要介绍

Iterator是专门的迭代输出接口,是集合输出中经常使用的一个接口,其本身是一个接口,要实例化操作必须借助Collection接口完成。

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接口实例化,这个方法在Collection接口中定义
while(iter.hasNext()){	// 判断是否有内容
System.out.println(iter.next()) ;	// 输出内容
}
}
};
运行结果:

hello

_

world

最主要的就是通过Collection接口中的iterator()这个方法实例化Iterator接口,再根据Iterator接口中的方法操作。输出时remove()方法只能用Iterator接口内的,而不要用集合类中的remove()方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: