Collections Framework
集合框架是一个统一的架构,用来表示和操作集合.
集合框架主要是由接口,抽象类和实现类构成.
接口:蓝色;实现类:红色
Collection
|_____Set(HashSet)
| |_____SortedSet(TreeSet)
|_____List(LinkedList,ArrayList)
Collection:集合层次中的根接口,JDK没有提供这个接口的实现类。
Set:不能包含重复的元素,子接口SortedSet是一个按照升序排列的元素的Set。
List:可以包含重复的元素,是一个有序的集合,提供了按索引访问的方式,有次序,位置不改变。
Collection接口常用的方法:
boolean |
add(E
o) 确保此 collection 包含指定的元素(可选操作)。 |
boolean |
contains(Object
o) 如果此 collection 包含指定的元素,则返回 true。 |
boolean |
remove(Object
o) 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。 |
int
|
size() 返回此 collection 中的元素数。 |
Object[] |
toArray() 返回包含此 collection 中所有元素的数组。 |
iterator() 返回在此 collection 的元素上进行迭代的迭代器。 |
List接口特有方法:
E |
get(int
index) 返回列表中指定位置的元素。 |
SortedSet接口特有方法:
E |
first() 返回此有序集合中当前第一个(最小的)元素。 |
E |
last() 返回此有序集合中最后一个(最大的)元素。 |
集合框架中的实现类.
ArrayList:
本质:我们可以将其看作是能够自动增长容量的数组,实际是采用对象数组实现的。
自动增长容量就是当数组不够的时候,再定义更大的数组,然后将数组元素拷贝到新的数组.
例子:import
Java.util.*;
class ArrayListTest
{
public static void main(String[] args)
{
ArrayList a1=new ArrayList();
a1.add("winsun");
a1.add("weixin");
a1.add("mybole");
for(int i=0;i<a1.size();i++)
{
System.out.println(a1.get(i));
}
System.out.println(a1);
}
}
结果:
winsun
weixin
mybole
[winsun, weixin, mybole]
利用ArrayList的toArray()返回一个对象的数组也可以利用Arrays.asList()方法返回一个列表
返回固定尺寸的列表,当返回以后就不能修改列表的大小了,可以修改列表中元素的值,但不能增加容量,可以用set()方法对值进行修改:
Object set(int index,Object element)
用element替换指定的index的对象
Arrays.asList()和Collection.toArray()是作为数组和集合类的一个桥
如果想从集合类中获得一个数组可以使用toArray()方法;如果想从数组中获得一个列表可以使用asList()方法 :
import java.util.*;
class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "x=" + x + ",y=" + y;
}
}
public class ArrayListToArrayTest {
public static void main(String[] args) {
ArrayList a1 = new ArrayList();
a1.add(new Point(3, 3));
a1.add(new Point(4, 4));
a1.add(new Point(5, 5));
for (int i = 0; i < a1.size(); i++) {
System.out.println(a1.get(i));
}
System.out.println(a1);
Object[] objs = a1.toArray(); // 利用ArrayList的toArray()返回一个对象的数组.
for (int i = 0; i < objs.length; i++) {
System.out.println(objs[i]);
}
System.out.println(objs);//
List l = Arrays.asList(objs);// Arrays.asList()返回一个列表.
System.out.println(l);
}
}
结果:
x=3,y=3
x=4,y=4
x=5,y=5
[x=3,y=3, x=4,y=4, x=5,y=5]
x=3,y=3
x=4,y=4
x=5,y=5
[Ljava.lang.Object;@1fc4bec
[x=3,y=3, x=4,y=4, x=5,y=5]
LinkedList类
LinkedList是采用双向循环链表实现的.
利用LinkedList实现栈(stack),队列(queue),双向队列(double-ended queue)
LinkedList常用方法
void addFirst(Object o)
void addLast(Object o)
Object getFirst()
Object getLast()
Object remove(int index)
boolean remove(Object o)
Object removeFirst()
Object removeLast()
判断是否为空
LinkedList继承了一个方法isEmpty()
如果没有包含任何元素返回true,没有包含任何元素返回false
ArrayList底层采用数组完成,而LinkedList则是以一般的
双向链表完成,其内每个对象除了数据本身外,还有两个引用,
分别指向前一个元素和后一个元素.
如果我们经常在List的开始处增加元素,或者在List中进行插入
和删除操作,我们应该使用LinkedList,否则的话,使用ArrayList
将更加快速.
因为插入和删除都要移动数组中的元素.
只是访问就用ArrayList,提供了按索引访问的机制.
HashSet
HashSet实现了Set接口的hash table(哈希表),依靠HashMap来实现.
应该为要存放到散列表的各个对象定义hashCode()和equals().
因为实现了set接口所以不能有重复的元素.
散列表:
散列表又称为哈希表.
散列表算法的基本思想:
以结点的关键字为自变量,通过一定的函数关系(散列函数)
计算出对应的函数值,以这个值作为该结点存储在散列表中的地址.
当散列表中的元素存放太满,就必须进行再散列,将产生一个新的散列表,
所有元素存放到新的散列表中,原先的散列表将被删除.
在java语言中,通过负载因子(load factor)来决定何时对散列表进行再
散列.例如:如果负载因子是0.75,当散列表中已经有75%的位置已经放满,
那么将进行散列.
负载因子越高(越接近1.0),内存的使用率越高,元素的寻找时间越长.
负载因子越低(越接近0.0),元素的寻找时间越短,内存浪费越多.
HashSet类的缺省负载因子是0.75.
HashSet在java.util包当中.
需要导入.
常用方法
boolean add(Object o)
需要使用迭代器
HashSet类实现了Set接口,所以不能有重复的元素.
要根据散列码计算存储位置.
而散列码是利用Object类当中的HashCode()函数获得的.
而HashCode()函数是通过一个对象的内存地址来得到散列码的.
所以要重写public int HashCode()方法.
String类实继承了HashCode()方法.
import java.util.*;
public class HashSetTest {
public static void main(String []args)
{
HashSet hs=new HashSet();
/* hs.add("one");
hs.add("two");
hs.add("three");
hs.add("one");
*/
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(2,"lisi"));
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(3,"wangwu"));
Iterator it=hs.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
class Student
{
int num;
String name;
Student(int num,String name)
{
this.name=name;
this.num=num;
}
public int HashCode()
{
return num*name.hashCode();
}
public boolean equals(Object o)
{
Student s=(Student)o;
return num==s.num && name.equals(s.name);
}
public String toString()
{
return "name : ="+name;
}
}
需要覆盖HashCode()和equals()方法
HashSet->HashCode->对象内存地址
TreeSet:
TreeSet是依靠TreeMap来实现的.
TreeSet是一个有序集合,TreeSet中元素将按照升序排列,
缺省是按照自然排序进行排列,意味着TreeSet中元素要
实现Comparable接口.
我们可以在构造TreeSet对象时,传递实现了Comparator接口
的比较器对象.
java.util包当中TreeSet类
import java.util.*;
public class TreeSetTest {
//如果自定义类对象要加入TreeSet要实现Comparable接口
public static void main(String []args)
{
TreeSet ts=new TreeSet(new Student.StudentComparator());
/* ts.add("winsun");
ts.add("weixin");
ts.add("mybole");
*/
ts.add(new Student(2,"lisi"));
ts.add(new Student(1,"wangwu"));
ts.add(new Student(3,"zhangsan"));
ts.add(new Student(3,"mybole"));
Iterator it=ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
class Student implements Comparable
{
int num;
String name;
static class StudentComparator implements Comparator
{
public int compare(Object o1,Object o2)
{
Student s1=(Student)o1;
Student s2=(Student)o2;
int result=s1.num>s2.num ? 1 : (s1.num==s2.num ? 0 : -1);
if(result==0)
{ //String类实现了compareTo()方法.
result=s1.name.compareTo(s2.name);
}
return result;
}
}
public static void printElements(Collection c)
{
Iterator it=c.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
Student(int num,String name)
{
this.name=name;
this.num=num;
}
public int HashCode()
{
return num*name.hashCode();
}
public boolean equals(Object o)
{
Student s=(Student)o;
return num==s.num && name.equals(s.name);
}
public int compareTo(Object o)
{
Student s=(Student)o;
return num>s.num?1:(num==s.num?0:-1);
}
public String toString()
{
return num+":"+name;
}
}
**
HashSet是基于Hash算法实现的,其性能通常优于TreeSet.
通常都应该使用HashSet,在需要排序的功能时,才使用
TreeSet.
**
迭代器:
Collection提供了一个iterator()方法,可以返回一个迭代器,迭代器是指向两个元素之间的指针。凡是继承自Collection的接口或间接的实现类都有这个方法.
其中有3个方法
1.hasNext()
2.next()
3.remove()
hasNext()判断是否有更多的元素,如果有返回true
remove()方法remove()方法需要删除上一个返回的元素,需要先调用next()方法后在用remove(),返回的列表有时不一定真正实现remove()方法,根据需要决定是否实现.
如:ArrayList al1=new ArrayList();
Iterator it=al.iterator();
it.next();
while(it.hasNext())
{
System.out.println(it.next());
}
通用方式访问集合中的元素
另外定义打印函数
public static void printElements(Collection c)
{
Iterator it=c.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
Map(HashMap)
|_____SortedMap(TreeMap)
Map:存储的是key-value对,不能包含重复的key,可以有重复的value。子接口SortedMap是一个按升序排列key的Map。
在系统区windows目录下有win.ini
有键和对应的值
asf=MPEGVideo
注册表存储的也是这种类型.
就是用Map接口所提供的方法来存储.
SortedMap是一个按照升序排列key的Map.
Map接口实现类:
HashMap:
对key进行散列.
keySet()..values()..entrySet()..
HashMap是实现了Map接口的Hash表.
实现了所有hashmap操作,允许空值和空键.
HashSet底层就是hashmap的实现.
map接口没有add()方法.
要放置元素通过put()方法.
Object put(Object key,Object value)
获取元素的时候
Object get(Object key)
通过键获取值
Hash表,通过键计算出相对应的存储位置的值,并输出.
常用的方法
Set keySet()
返回一个键的视图类型是Set.
Collection values()
返回一个值的视图类型是Collection.
Set entrySet()
返回一个键值对视图类型是Set.
返回的Set集合当中每一个对象都是一个Map.Entry对象.
Map.Entry是一个静态的接口.
接口中提供了常用方法
Object getKey()
Object getValue()
*****************************
import java.util.*;
public class HashMapTest
{
public static void printElements(Collection c)
{
Iterator it=c.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
public static void main(String []args)
{
HashMap hm=new HashMap();
hm.put("1", "zhang3");
hm.put("2", "li4");
hm.put("3", "wang5");
System.out.println(hm.get("1"));
System.out.println(hm.get("2"));
System.out.println(hm.get("3"));
Set keys=hm.keySet();
System.out.println("-----------keys---------");
printElements(keys);
Collection values=hm.values();
System.out.println("-----------values---------");
printElements(values);
Set entrySets =hm.entrySet();
System.out.println("------------entrySets-----------");
printElements(entrySets);
Iterator it=entrySets.iterator();
while(it.hasNext())
{
Map.Entry me=(Map.Entry)it.next();
System.out.println(me.getKey()+" = "+me.getValue());
}
}
}
**
TreeMap是实现了sorted Map接口的类
TreeMap按照key进行排序.
类似HashMap用法
**********************
HashMap和TreeMap比较
和Set类似,HashMap的速度通常都比TreeMap快,
只有在需要排序的功能的时候,才使用TreeMap.
另外有用的类
Collections类不同于Collection类
Collections.sort()主要是对列表排序.
1.自然排寻natural ordering
2.实现比较器Comparator接口
取最大元素Collections.max().
取最小元素Collections.min().
在已经排序的List中搜索指定的元素.
Collections.binarySearch().
static void sort(List list)方法是按升序对指定列表排序.
自然排序法.
列表中元素必须都实现了comparable接口.与Arrays.sort()是一样的.
comparable接口在java.lang包当中.
实现comparable接口就要实现compareTo()方法.
compareTo()大于返回正数,等于返回0,小于返回负数.
class Student implements Comparable
{
int num;
String name;
Student(int num,String name)
{
this.num=num;
this.name=name;
}
public int compareTo(Object o)
{
Student s=(Student)o;
return num>s.num?1:(num==s.num?0:-1);
}
public String toString()
{
return num+":"+name;
}
}
public static void printElements(Collection c)
{
Iterator it=c.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
public static void main(String []args)
{
Student s1=new Student(2,"zhangsan");
Student s2=new Student(1,"lisi");
Student s3=new Student(3,"wangwu");
ArrayList a1=new ArryList();
a1.add(s1);
a2.add(s2);
a3.add(s3);
Collections.sort(a1);
printElements(a1);
}
排序的时候可以传递一个比较器.
Comparator接口.
java.util包当中.
有两个方法int compare(Object o1,Object o2)
两个对象进行比较当对象1大于对象2的时候返回1,
当对象1等于对象2的时候返回一个0,
当对象1小于对象2的时候返回一个负数.
和boolean equals(Object obj)方法.
实现一个比较器.
比较器总是和一个特定的类相关.
为某一个类指定一个比较器.
利用内部类实现比较器接口.
**内部类
声明为静态方法就不需要产生外部类对象.
class Student implements Comparable
{
int num;
String name;
Student(int num,String name)
{
this.num=num;
this.name=name;
}
public int compareTo(Object o)
{
Student s=(Student)o;
return num>s.num?1:(num==s.num?0:-1);
}
public String toString()
{
return num+":"+name;
}
static class StudentComparator implements Comparator
{
public int compare(Object o1,Object o2)
{
Student s1=(Student)o1;
Student s2=(Student)o2;
int result=s1.num>s2.num ? 1 : (s1.num==s2.num ? 0 : -1);
if(result==0)
{ //String类实现了compareTo()方法.
result=s1.name.compareTo(s2.name);
}
return result;
}
}
}
public static void printElements(Collection c)
{
Iterator it=c.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
public static void main(String []args)
{
Student s1=new Student(2,"zhangsan");
Student s2=new Student(1,"lisi");
Student s3=new Student(3,"wangwu");
ArrayList a1=new ArryList();
a1.add(s1);
a2.add(s2);
a3.add(s3);
Collections.sort(a1,Student.StudentComparator());
printElements(a1);
}
Collections类中提供了一种反序排列方式.
本身返回就是一个比较器对象
static Comparator reverseOrder()
Arrays.sort()也可以指定一个比较器对象
static void sort(Object[] a,Comparator c)
Collections类主要对列表操作.
Arrays类主要对数组操作.
Vector集合类
Vector:用ArrayList代替Vector.
Vector内所有方法都是同步的,存取元素效率低.
在多线程中可以使用
在Collection类中提供了
static list synchronizedList(List list)
可以返回一个同步列表
可以将列表实参传递进去会返回一个安全的线程同步列表
还有
static Collection synchronizedCollection(Collection c)
static Set synchronizedSet(Set s)
Hashtable:用HashMap代替Hashtable
需要同步Map的时候
可以用Collection类的方法
static Map synchronizedMap(Map m)
但是还是Hashtable获取的同步Map快一些.
Stack集合类:
Stack:用LinkedList代替Stack.
Stack是从java.util.Vector继承而来.
还从Vector继承了alementAt()方法.
同时Stack还继承了不需要的特性.
所以要使用栈的时候要用LinkedList来自己实现.
Properties属性类.是从Hashtable继承而来也是存储键值对的.
表示一个持久的属性集合.
可以存储win.ini的键值对.
在
java.lang.System类当中
有
static Properties getProperties()
检测当前系统的属性
可以使用
void list(PrintStream out)打印系统属性
还可以读取一个配置文件:
先建立一个配置文件
winsun.ini
写入
company=winsun
author=sunxin
corpyright=2003-2004
先实例化一个Property对象
在用
void load(InputStream inStream)方法
可以从一个输入流中加载一个属性列表.
输入流可以用java.io包中的一个类构造.
可用
Enumeration propertyNames()
返回Enumeration对象.返回所有键的枚举.
Enumeration是一个接口
提供了两个方法
boolean hasMoreElements()
Object nextElement()
需要返回值的时候
String getProperty(String key)
返回键对应的值
import java.util.*;
import java.io.FileInputStream;
import java.io.*;
public class ProTest {
public static void main(String []args)
{
/* Properties pps=System.getProperties();
pps.list(System.out);
*/
Properties pps=new Properties();
try
{
pps.load(new FileInputStream("d:/workspace/ProTest/bin/winsun.ini"));
Enumeration ENUM=pps.propertyNames();
while(ENUM.hasMoreElements())
{
String str=(String)ENUM.nextElement();
String strValue=pps.getProperty(str);
System.out.println(str+" = "+strValue);
}
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
static String getProperty(String key)
static String getProperty(String key,String def)