Java集合框架
类集的概念是在JDK1.2之后正式完善的一套开发架构,基本的作用是完成一个动态的对象数组,里面的数据元素可以动态增加。
注意:Java集合只能存放对象,不能存放其本数据类型,就算是放了基本数据类型也会自动进行打包,更不能存放变量。
Collection接口(重点)
Collection接口是一个重要的操作接口,其中规定了一个集合的基本操作方法,此接口有2个子接口。
Collection的定义:
public interface Collection<E>extends Iterable<E> |
在JDK1.5之后,Collection使用了泛型。
Collection接口定义如下的方法:
NO | 方法 | 描述 |
1 | boolean add(E e) | 增加一个元素 |
2 | boolean addAll(Collection<? Extends E> c) | 增加一组数据,泛型指定了操作的上限 |
3 | void clear() | 移除此 collection 中的所有元素 |
4 | boolean remove(Object o) | 删除Collection的指定元素 |
5 | boolean removeAll(Collection<?> c) | 删除Collection指定的一组元素 |
6 | boolean retainAll(Collection<?> c) | 保留Collection指定的一组元素 |
7 | int size() | 返回Collection元素的个数 |
8 | boolean isEmpty() | 判断是否为空 |
9 | boolean contains(Object o) | 判断是否包含某个元素 |
10 | boolean containsAll(Collection<?> c) | 判断是否包含一组元素 |
11 | Object[] toArray() | 返回包含此 collection 中所有元素的数组。 |
12 | <T> T[] toArray(T[] a) | 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。 |
现在开发一部很少去使用Collection完成功能了,基本上都使用了其子类的接口:List、Set
1.3、List接口(重点)
List接口定义:
public interface List<E>extends Collection<E> |
List接口的最大特点是里面的内容都允许重复,此接口相对Collection也扩充了很多方法,增加的方法如下:
NO | 方法 | 描述 |
1 | void add(int index,E element) | 在指定的位置增加一个元素 |
2 | boolean addAll(int index, Collection<? extends E> c) | 将指定 collection 中的所有元素都插入到列表中的指定位置 |
3 | E get(int index) | 返回列表中指定位置的元素 |
4 | E remove(int index) | 删除定义位置的内容 |
5 | E set(int index,E element) | 修改指定位置的内容 |
6 | List<E> subList(int fromIndex, int toIndex) | 截取list,fromIndex<= X <toIndex |
1.3.1、新的子类:ArrayList
ArrayList是List接口最常用的一个子类,其定义如下:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable |
使用ArrayList类可以直接为List接口实例化。
package com.jtlyuan.collection.list; import java.util.ArrayList; import java.util.List; public class ArrayListDemo { public static void main(String[] args) { List<String> myList = new ArrayList<String>();//实例化ArrayList myList.add("hello");//增加元素 myList.add("jtlyuan"); myList.add("帅哥"); myList.add("呵呵"); myList.add("帅哥"); myList.add(3, "OKOK");//在指定的位置增加元素 System.out.println(myList); myList.remove(1);//根据索引来删除一个元素 myList.remove("帅哥");//更加对象删去第一个帅哥对象 System.out.println(myList); System.out.println(myList.get(3)); System.out.println(myList.size()); System.out.println(myList.subList(1, 3)); } }/* [hello, jtlyuan, 帅哥, OKOK, 呵呵, 帅哥] [hello, OKOK, 呵呵, 帅哥] 帅哥 4 [OKOK, 呵呵]*/ |
1.3.2旧的子类:Vector
Vector类是一个元老级的操作类,在JDK1.0就开始有了,而Array是在JDK1.2之后才有的新的操作。Vector也实现了List接口。
Vector的定义:
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable |
Vector现在比较少用了,里面的操作基本与List相同
1.3.3、ArrayList与Vector的区别:
NO | 区别点 | ArrayList | Vector |
1 | 推出时间 | JDK1.2新类 | JDK1.0旧类 |
2 | 操作 | ArrayList是异步处理操作 | Vector采用了同步的处理操作 |
3 | 性能 | ArrayList性能高 | Vector性能相对低 |
4 | 安全 | 非线程安全 | 线程安全 |
1.3.4、LinkedList类和Queue接口(了解)
LinkedList的定义:
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable |
范例说明:
package com.jtlyuan.collection.list; import java.util.LinkedList; import java.util.List; public class LinkedListDemo { public static void main(String[] args) { LinkedList<String> myList = new LinkedList<String>(); myList.add("A"); myList.add("B"); myList.add("C"); myList.addFirst("X"); myList.addLast("Y"); System.out.println(myList.getFirst()); System.out.println(myList); } }/* X [X, A, B, C, Y]*/ |
1.4、Set接口(重点)
Set接口也是Collection的子接口,最大的特点是没有重复元素。在Set接口中有以下的两个子类的常用的:
·HashSet:散列存放
·TreeSet:有序存放
Set接口本身继承了Collection却没有扩充Collection接口
1.4.1、散列存放:HashSet(没有重复、没有顺序)
HashSet范例:
public class HashSetDemo { public static void main(String[] args) { Set<String> mySet = new HashSet<String>(); mySet.add("编程"); mySet.add("之美"); mySet.add("编程"); mySet.add("珠玑");//重复元素,但是能够编译 System.out.println(mySet); } } /*[珠玑, 编程, 之美]*/ |
可以看出来:HashSet元素不能重复,若是重复也能编译,而且对象之间没有顺序
1.4.2、有序存放:TreeSet(没有重复对象、内部根据cmparaTo()方法自动进行排序)
public class TreeSetDemo { public static void main(String[] args) { Set<String> mySet = new TreeSet<String>(); mySet.add("A"); mySet.add("D"); mySet.add("G"); mySet.add("B"); mySet.add("C"); mySet.add("F"); mySet.add("E"); System.out.println(mySet); } } /*[A, B, C, D, E, F, G]]*/ |
1.4.3、关于排序的说明
在之前的操作中使用的是String类的对象向集合中加入,如果自定义一个类呢?
定义一个Person类:
public class Person { String name; int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "[姓名" + name + ", 年龄=" + age + "]"; } } |
public class TreeSetAddPerson { public static void main(String[] args) { Set<Person> mySet = new TreeSet<Person>(); mySet.add(new Person("张三",1)); mySet.add(new Person("李四",2)); mySet.add(new Person("王五",2)); System.out.println(mySet); } } |
Exception in thread "main" java.lang.ClassCastException: com.jtlyuan.collection.set.Person cannot be cast to java.lang.Comparable at java.util.TreeMap.put(TreeMap.java:542) at java.util.TreeSet.add(TreeSet.java:238) at com.jtlyuan.collection.set.TreeSetAddPerson.main(TreeSetAddPerson.java:10) |
呵呵,出错啦,因为TreeSet是要进行排序的,任何的对象要进行排序,则必须要实现Comparable接口的comparaTo()方法。
所有把Person改为如下:
public class Person implements Comparable<Person>{ String name; int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "[姓名" + name + ", 年龄=" + age + "]"; } @Override public int compareTo(Person o) { if(this.age>o.age){ return 1; }else if(this.age<o.age){ return -1; }else{ return 0; } } } |
运行代码:输入答案为:
[[姓名张三, 年龄=1], [姓名李四, 年龄=2]] |
为什么呢?三个对象,变为了2两个对象。原来是因为Comparable中comparaTo()方法比较的是利用age来比较,所有age相同的对象在排序的时候就默认为同一个对象。所有就没有加上去了哦。为了解决这样的问题在下面修改Comparable的comparaTo方法的返回值要关联name属性。
@Override public int compareTo(Person o) { if(this.age>o.age){ return 1; }else if(this.age<o.age){ return -1; }else{ return this.name.compareTo(o.name); } } |
运行打印了
[[姓名张三, 年龄=1], [姓名李四, 年龄=2], [姓名王五, 年龄=2]] |
3.4.4、关于重复元素的说明
如果把TreeSet改为HashSet则会出现重复的元素。因为new了两个一样的对象,为了避免这样的情况发生,必须要复写Object的equal()和hashCode()方法来确定两个不同的对象。
package com.jtlyuan.collection.set; public class Person implements Comparable<Person>{ String name; int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "[姓名" + name + ", 年龄=" + age + "]"; } @Override public int compareTo(Person o) { if(this.age>o.age){ return 1; }else if(this.age<o.age){ return -1; }else{ return 0; } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Person)) return false; Person other = (Person) obj; if(other.age==this.age&&other.name==this.name){ return true; } return false; } } |
运行结果:
[[姓名李四, 年龄=2], [姓名王五, 年龄=2], [姓名张三, 年龄=1]] |
1.5、集合输出:
集合输出有Iterator、ListIterator、foreach、Enumeration;但是我们一遇到集合的输出,马上想到用Iterator实现遍历、取值
范例:
package com.jtlyuan.collection.iterator; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class IteratorDemo { public static void main(String[] args) { List<String> myList = new ArrayList<String>(); myList.add("梁任元"); myList.add("梁"); myList.add("任"); myList.add("元"); Iterator it = myList.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } } |
1.6、Map接口
Collection接口是保存单值最大的父接口,而Map接口是保存一对值(key—value)的最大的接口。Map中的key是不能重复的。
Map接口有三个常用子类:
·HashMap、HashTable、TreeMap
Map接口的常用方法如下:
NO | 方法 | 描述 |
1 | boolean containsKey(Object key) | 此映射是否包含指定键的映射 |
2 | boolean containsValue(Object value) | 此映射是否包含指定值的映射 |
3 | V get(Object key) | 返回指定键所映射的值 |
4 | put(K key,V value) | 向此Map实例增加内容 |
5 | 从映射中移除其映射关系的键,返回与 key 关联的值;如果没有 key 的映射关系,则返回 null。 | |
6 | int size() | 求映射的程度 |
7 | boolean isEmpty() | 判断映射是否为空 |
8 | 返回此映射中包含的键的 | |
9 | Collection<V> values() | 返回此映射中包含的值的 |
1.6.1、新的子类:HashMap(重点)
HashMap是一个新的操作类,HashMap是无序的。Map中的key是不能重复的,如果重复了,则属于覆盖,即保留了后来增加的内容。Map最大的特点是查找操作,如果查找到了则返回Value,否则返回null值。
范例:
package com.jtlyuan.map.hashmap; import java.util.HashMap; import java.util.Map; public class HashMapDemo { public static void main(String[] args){ Map<String,Integer> myMap = new HashMap<String,Integer>(); myMap.put("A", 1); myMap.put("B", 2); myMap.put("C", 3); myMap.put("C", 3); System.out.println(myMap); System.out.println(myMap.get("A")); System.out.println(myMap.get("jtlyuan")); } } /* {D=4, A=1, B=2, C=3} 1 null */ |
除了此操作外,还有其他的操作,看API或上面的表
1.6.2、旧的子类:Hashtable(重点)
Hashtable实际上和Vector是同时产生的都是属于线程安全的。其操作和Map几乎一样。
HashMap与Hashtable的比较:
NO | 区别点 | HashMap | Hashtable |
1 | 推出时间 | JDK1.2新类 | JDK1.0旧类 |
2 | 操作 | HashMap是异步处理操作 | Hashtable采用了同步的处理操作 |
3 | 性能 | HashMap性能高 | Hashtable性能相对低 |
4 | 安全 | 非线程安全 | 线程安全 |
1.6.3、有排序的子类:TreeMap是按照key来排序的(重点)
范例:
package com.jtlyuan.map.hashmap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class HashMapDemo { public static void main(String[] args){ Map<String,Integer> myMap = new TreeMap<String,Integer>(); myMap.put("A", 1); myMap.put("B", 2); myMap.put("C", 3); myMap.put("C", 3); myMap.put("D", 4); System.out.println(myMap); Set<String> set = myMap.keySet(); Iterator it = set.iterator(); while(it.hasNext()){ String str = (String) it.next(); System.out.println(str+" --> "+myMap.get(str)); } } } /*{A=1, B=2, C=3, D=4} A --> 1 B --> 2 C --> 3 D --> 4 */ |
如果key的类型的任意对象类型,要TreeMap能够自动进行排序的话,则此类必须实现Comparable的comparaTo()方法。
注意事项一、Map不能直接使用Iterator输出。
因为Map里面是由一个Map.Entry实体的组成的,此对象才是真正的保存key—value操作。
注意事项二、使用非系统类的对象作为key或value,则要重写equal()方法和hashCode()方法。
1.7、Static
有push、pop等方法
1.8、属性操作类:Properties
Properties
类表示了一个持久的属性集。可以把信息保存在*.properties文件和*.xml中,也可以从*.peoperties和*.xml中读取信息。注意此类的全部属性都是String对象
Properties类中的主要方法:
NO | 方法 | 描述 |
1 | public Object setProperty(String key, String value) | 设置属性 |
2 | public String getProperty(String key) | 获取属性 |
3 | public String getProperty(String key, String defaultValue) | 获取属性,找不到返回默认值defaultValue |
4 | public void list(PrintStream out) | 输出所有属性 |
5 | public void store(OutputStream out, String comments) throws IOException | 将Properties对象保存在*.properties中。out - 输出流。 comments - 属性列表的描述 |
6 | public void load(InputStream inStream) throws IOException | 将*.properties中的所有属性获取到Properties对象中。 |
7 | public void storeToXML(OutputStream os, String comment) throws IOException | 将Properties对象保存在*.xml中。out - 输出流。 comments - 属性列表的描述 |
8 | public void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException | 将*.xml中的所有属性获取到Properties对象中。 |
1、把属性保存在*.properties中
package com.jtlyuan.properties; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; public class PropertiesDemo { public static void main(String[] args) throws FileNotFoundException { Properties pro = new Properties(); pro.setProperty("A", "1"); pro.setProperty("B", "2"); pro.setProperty("C", "3"); pro.setProperty("D", "4"); File file = new File("d:"+File.separator+"demo.properties"); OutputStream out = new FileOutputStream(file); try { pro.store(out, "shuoming"); } catch (IOException e) { e.printStackTrace(); } } } |
可以在D:\demo.prioperties文件中保存着:
#shuoming
#Wed Mar 14 17:49:17 CST 2012
A=1
D=4
C=3
B=2
2、从*.properties中取出属性
package com.jtlyuan.properties; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; public class PropertiesDemo { public static void main(String[] args) throws FileNotFoundException { Properties pro = new Properties(); pro.setProperty("A", "1"); pro.setProperty("B", "2"); pro.setProperty("C", "3"); pro.setProperty("D", "4"); File file = new File("d:"+File.separator+"demo.xml"); OutputStream out = new FileOutputStream(file); try { pro.store(out, "shuoming"); } catch (IOException e) { e.printStackTrace(); } } } |
|
可以在D:\demo.xml文件中保存着:
#shuoming
#Wed Mar 14 17:53:36 CST 2012
A=1
D=4
C=3
B=2
从*.properties中拿出属性
package com.jtlyuan.properties; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class PropertiesDemo { public static void main(String[] args) throws FileNotFoundException { Properties pro = new Properties(); pro.setProperty("A", "1"); pro.setProperty("B", "2"); pro.setProperty("C", "3"); pro.setProperty("D", "4"); File file = new File("d:"+File.separator+"demo.xml"); InputStream in = new FileInputStream(file); try { pro.load(in); } catch (IOException e) { e.printStackTrace(); } System.out.println(pro.getProperty("A")); } } /* 1 */ |
从*.xml中拿出属性:
package com.jtlyuan.properties; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class PropertiesDemo { public static void main(String[] args) throws FileNotFoundException { Properties pro = new Properties(); pro.setProperty("A", "1"); pro.setProperty("B", "2"); pro.setProperty("C", "3"); pro.setProperty("D", "4"); File file = new File("d:"+File.separator+"demo.properties"); InputStream in = new FileInputStream(file); try { pro.load(in); } catch (IOException e) { e.printStackTrace(); } System.out.println(pro.getProperty("A")); } } /* 1 */ |
总结:
1、类集合设置的主要目的是实现动态的对象数组操作。
2、collection是存放单值的最大父接口。所有超级terator接口
3、List接口允许值的重复。其子类有:ArraryList(最采用)、Vector(旧的类)、LinkedList(允许null值,实现了Queue接口)
4、Set接口:不允许对象重复,依靠equal()和hashCode()【注意:java中默认hashCode的根据对象的地址计算得来的】方法来检查区分是否为同一对象。
HashSet:无序的
TreeSet:能够按照y对象的comparaTo()方法。
5、Map接口:存放一对值,key不能重复。不能放空值,Map并没有继承Collection接口
HashMap:无序的
Hashtable:无序的而且同步的,线程安全的,旧的类(不允许关键字或值为null
TreeMap,:能够按照key自动来排序,按照Key对象的comparaTo()方法。
6、注意集合的工具类Collections与Collection的区别
原文:http://blog.csdn.net/jtlyuan/article/details/7346922