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。下面就对这两个常用的接口以及子接口和子类做一些介绍。
对于Iterable<E>这个接口之后会介绍到,先说Collection<E>这个接口,它有两个常用的子接口List<E>,Set<E>,常用操作add()加入元素,remove()移除元素,clear()清空所有元素,iterator()访问
在List中可以存放任意的数据,内容可以重复,同时也是有序的,List这个接口也有继承自己的子类:ArrayList, LinkedList, Vector
[World, Hello]
[A, B, World, Hello, A, B]
由前向后输出:World、Hello、Hello、A、B、
由后向前输出:B、A、Hello、Hello、World、
这里也可以将ArrayList中的元素转化成数组的形式在输出,如:
ArrayList 采用异步的方式处理,性能高,非线程安全操作类,只能用Iterator foreach 输出
Vector 同步的方式处理,性能较低,属于线程安全操作类,可以用Iterator foreach Enumeration输出
初始化链表:[A, B, C]
增加头和尾之后的链表:[X, A, B, C, Y]
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()在表为空是会抛出异常:
Set接口也是Collection的接口,但是不允许加入重复元素,它也有常用子类HashSet,TreeSet
[姓名:王五;年龄:32, 姓名:赵六;年龄:33, 姓名:孙七;年龄:33, 姓名:王五;年龄:32, 姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32]
会发现这里没有去除相同的对象,所以需要Object类中的两个方法hashcode(),equals();而之前加入的对象是String类,其中已经覆写了这两个方法。
取出的内容是:b
搜索的key存在!
搜索的value不存在!
在Map中加入数据时用put()方法,还有remove()移除一个元素,clear()清除等方法,containsKey(),containsValue()这个两个方法是根据键值映射值键,返回值为boolean型。接下来对输出做简单的介绍(毕竟查找才是map接口的主要作用),输出所有的key值,所有的vaule值:
输出所有key时用到了Set<K> keySet()这个方法,而输出所有的value时用Collction<K> values(),其实可以想到,Key值的唯一性是的在向上转型只能用Set接收。
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>
运行结果:
A --> a
B --> b
C --> c
Map.Entry<K,E>中存放Map的键值对,通过getKey()方法和getValue()方法得到,以上是通过foreach的方式输出。如果是自定义类作为key值:
在上例类中需要覆写以上两个方法。最后对开始提到的Iterator接口简要介绍
Iterator是专门的迭代输出接口,是集合输出中经常使用的一个接口,其本身是一个接口,要实例化操作必须借助Collection接口完成。
hello
_
world
最主要的就是通过Collection接口中的iterator()这个方法实例化Iterator接口,再根据Iterator接口中的方法操作。输出时remove()方法只能用Iterator接口内的,而不要用集合类中的remove()方法。
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()方法。
相关文章推荐
- eclipse 简介
- Java Switch支持的类型问题
- springmvc bean初始化
- java中值传递问题
- Java 获取指定时间的前一天Date
- JAVA下载文件
- Java IO文件流
- JAVA 冒泡排序-个人理解
- web项目中javax.servlet.ServletExcecption: java.lang.ClassNotFoundException: com.mysql.jdb.Driver
- Java知识结构思维导图
- Spring MVC 原理小结
- myeclipse-10.7-offline-installer-windows安装图解及注意事项
- java forEach实现原理
- 关于JAVA IO流写文件数字乱码的问题
- 近期最久未使用页面淘汰算法———LRU算法(java实现)
- Java基础几个问题
- Java基础学习第五天——方法与数组
- Java并发编程:Callable、Future和FutureTask
- Java初涉之10--Java位运算
- Java基础学习第四天——选择与循环结构