java提供两种存储对象的方式:数组和
集合类。
两者的主要区别:
1,数组的长度固定,集合类长度是可变的;
2,数组既可以存储对象也可以存储基本数据类型,而集合类只能存储对象;
java集合框架体系结构:
|--Collection
接口:
|--Set接口:
|--HashSet具体类
|--LinkedHashSet具体类
|--TreeSet具体类
|--List接口:
|--ArrayList具体类
|--LinkedList具体类
|--向量类Vector具体类
|--Stack具体类
其中java.util.Collection中定义了Set集合和List集合的根接口,其中定义了两个集合都包含的抽象方法:size,Iterator,add,remove,equals,
hashCode等。
java.util.List定义了List集合的接口, List集合的主要特点:元素有序(元素读入取出一致)且可重复(有索引)。包含Collection中的所有方法的同时,还定义了额外的一些抽象方法主要有:ListIterator,set(修改某一位置上的元素),subList(返回起始位置到结束位置的一个子List),get(返回指定位置上的元素)等。
Code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public
class Test{
public static void main(String[] args) {
ArrayList al = new ArrayList();
ArrayList al1 = new ArrayList();
al.add("01");
al.add("02");
al.add("03");
al.add("04");
al1.addAll(al);//list添加一个集合的方法
System.out.println(al.indexOf("03"));//返回该元素的索引位置的函数
System.out.println(al.isEmpty());//判断是否为空的函数
System.out.println(al1);
System.out.println(al.subList(1, 3));//获取子List的方法包含开始位置,不包含结束位置。
for(int i = 0 ; i<al.size();i++){
System.out.println(al.get(i));//返回指定索引位置的元素
}
al.set(2, "05");//修改指定位置上的元素为
Iterator it = al.iterator();
while (it.hasNext()) {
System.out.println(it.next());
/*if(it.next() == "02"){ 使用迭代器来获取每一个值时,不能同时对该List进行修改操作,会抛出
al.add("001"); ConcurrentModificationException
异常。
}*/
}
ListIterator lit = al.listIterator();
while (lit.hasNext()) {
Object object = lit.next();//List集合特有的一个迭代器ListIterator
if(object.equals("02"))
lit.add("003");
}
al.removeAll(al1);//对al删除al1中包含的所有元素
al.retainAll(al1);//al中只保留与al1共有的元素中
}
}
其中java.util.Iterator接口中只定义了三个方法:hasNext(),next(),remove()。对于List如果想要在迭代的同时进行更多的操作,则需要使用ListIterator,它是java.util.Iterator接口的一个子接口。该接口只能通过List集合的listIterator方法来获取,其中定义了对List的更多操作:add();set();hasPrevious()(用以逆向遍历List)等。
List接口包含主要三个具体实现方式:
ArrayList类:底层使用数组。特点:查询快,增删较慢(
线程不
同步)
LinkedList类:底层使用链表。特点:查询慢,增删快
Vector类:底层使用数组。它除了包含访问和修改向量的同步方法之外,跟ArrayList一样。(线程同步)
Stack类:它继承自Vector类,,但一般只作为栈的功能来使用,不要去使用Vector里面的功能
注:集合类的长度是可变的,而数组长度是固定的。使用数组实现可变长度的方式:一个默认数组长度为10,如果数组长度不够。ArrayList 超长后50%延长,Vector 100%增长
vector特有的特性:
Code:
import java.util.Enumeration;
import java.util.Vector;
public class Test{
public static void main(String[] args) {
Vector v = new Vector();
v.add("01");
v.add("02");
Enumeration en = v.elements();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
}
}
Vector包含一个特有的元素遍历方法:使用
枚举接口java.util.Enumeration。和迭代器的功能是一样的,因为枚举的名称及方法的名称过长,所以被迭代器取代。
LinkedList特有特性:
getFist();//返回第一个元素
getLast();//返回最后一个元素
addFirst();//往头部添加元素
addLast();//往尾部添加元素
removeFirst();//移除头部元素并返回(与get的区别在于返回之后删除)
removeLast();//移除尾部元素并返回
如果集合中没有元素会出现异常: NoSuchElementException
1.6之后替换为:
offerFirst();
offerLast();
peekFirst();
peekLast();
pollFirst();
pollLast();
集合中没有元素时返回null而不抛出异常
Code(使用LinkedList来模拟栈)
import java.util.LinkedList;
class stack {
private LinkedList ll = new LinkedList();
stack(){
ll = new LinkedList();
}
public void add(Object obj){
ll.offerLast(obj);
}
public Object get(){
return ll.pollLast();
}
public Boolean isNull(){
return ll.isEmpty();
}
}
public class Test{
public static void main(String[] args) {
stack s= new stack();
s.add("01");
s.add("02");
System.out.println(s.get());
}
}
java.util.Set定义了Set集合的接口,Set集合的主要特点:元素无序,元素不可重复。包含的方法与Collection中的方法一样。
Set接口有3种实现:(底层使用map来实现)
HashSet类底层由哈希表来实现的。必须实现hashCode方法,javaAPI大多数类实现了hashCode方法。
LinkedHashSet类实现了对HashSet的扩展,支持规则集内元素的排序,在HashSet中元素是没有顺序的,而在LinkedHashSet中,可以按元素插入集合的顺序进行提取
TreeSet类底层由二叉排序树实现的。保证集中的元素是有序的,有2种方法可以实现对象之间的可比较性:1,添加到TreeSet的对象实现了Comparable接口;2,给规则集的元素指定一个比较器(Comparator)
HashSet类Code:
import java.util.HashSet;
import java.util.Iterator;
class student {
private int age;
private String name;
public student(String name ,int age) {
this.name = name;
this.age = age;
}
public String getname() {
return name;
}
public int getage(){
return age;
}
public int hashCode(){
return 1;
}
public boolean equals(Object o){
if (!(o
instanceof student)) {
return false;
}
student s = (student)o;
System.out.println(this.getname()+"----"+s.getname());
return this.age == s.age && this.name.equals(s.name);
}
}
public class Test{
public static void main(String[] args) {
HashSet hs= new HashSet();
hs.add(new student("zhangsan", 11));
hs.add(new student("lisi", 12));
hs.add(new student("wangwu", 11));
Iterator it = hs.iterator();
while (it.hasNext()) {
student s = (student)it.next();
System.out.println(s.getname()+"!!"+s.getage());
}
}
}
【运行结果】
lisi----zhangsan
wangwu----lisi
wangwu----zhangsan
wangwu!!11
lisi!!12
zhangsan!!11
从结果我们可以看出,HashSet保证元素唯一性的方法是通过先判断hashCode()方法再判断equals()方法来确实。内部调用。所以当我们封装一个对象时,务必重写equals和hashCode方法。(HashSet的contains和remove方法均内部调用了hashCode和equals方法,先调用hashCode再调用equals)
TreeSet
提供排序功能的Set,底层为树结构。相比较HashSet其查询速度低,如果只是进行元素的查询,我们一般使用HashSet。
TreeSet保证集中的元素是有序有2种实现方法:
1,实现对象之间的具有可比较性,即添加到TreeSet的对象实现了Comparable接口;
2,给规则集的元素指定一个比较器(Comparator)。(都存在时以比较器为主)
java.lang.Comparable接口只有一个方法:compareTo()比较两对象之间的大小,返回正整数、0、负整数。
Code:
import java.util.Iterator;
import java.util.TreeSet;
class student implements Comparable {
private int age;
private String name;
public student(String name ,int age) {
this.name = name;
this.age = age;
}
public String getname() {
return name;
}
public int getage(){
return age;
}
public int compareTo(Object o){
if(!(o instanceof student))
throw new RuntimeException("不是学生");
student s = (student) o;
System.out.println(this.name+"-----"+s.name);
int num = new Integer(this.age).compareTo(s.age);//会自动对int进行装箱,Integer实现了comparable接口
if(num == 0)
return this.name.compareTo(s.name);//string也实现了comparable接口
return num;
}
}
public class Test {
public static void main(String[] args) {
TreeSet ts= new TreeSet();
ts.add(new student("zhangsan", 11));
ts.add(new student("lisi", 11));
ts.add(new student("wangwu", 11));
Iterator it = ts.iterator();
while (it.hasNext()) {
student s = (student)it.next();
System.out.println(s.getname()+"!!"+s.getage());
}
}
} 【运行结果】
lisi-----zhangsan
wangwu-----zhangsan
wangwu-----lisi
lisi!!11
wangwu!!11
zhangsan!!11
TreeSet保证数据唯一性的方式就是对每个元素调用其包含的compareTo方法,来实现同时完成排序。
当我们想要定义自己的比较方法,而不使用对象内部的比较方法或者元素本身就不具备比较性时。java提供了java.util.Comparator接口使集合自身具备比较方法。java.util.Comparator接口中包含两个方法:compare(Object o,Object o1)和equals方法用于提供比较方法。
Code:
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
class student {
private int age;
private String name;
public student(String name ,int age) {
this.name = name;
this.age = age;
}
public String getname() {
return name;
}
public int getage(){
return age;
}
}
public class Test{
public static void main(String[] args) {
TreeSet ts= new TreeSet(new myComparator());
ts.add(new student("zhangsan", 11));
ts.add(new student("lisi", 11));
ts.add(new student("wangwu", 11));
Iterator it = ts.iterator();
while (it.hasNext()) {
student s = (student)it.next();
System.out.println(s.getname()+"!!"+s.getage());
}
}
}
class myComparator implements Comparator{
public int compare(Object o, Object o1) {
if(!(o instanceof student) || !(o1 instanceof student))
throw new RuntimeException("不是学生");
student s = (student) o;
student s1 = (student) o1;
System.out.println(s.getname()+"-----"+s1.getname());
int num = new Integer(s.getage()).compareTo(s1.getage());
if(num == 0)
return s.getname().compareTo(s1.getname());
return num;
}
}
结果与上面一致。