Java集合类(Set和List)

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;

}
}
结果与上面一致。

你可能感兴趣的:(java)