集合类Collection
集合是存储对象的容器,以便于对多个对象进行操作
集合与数组的区别
数组也可以存储对象,但是长度固定,集合的长度可变
数组还可以存储基本数据类型,集合只能存储对象
集合的特点:
只用于存储对象,且可以存储不同类型的对象,长度可变
集合框架
集合相关的API可以分为三类:接口(Interface)、实现类(Implementation)、抽象类(Abstract)
这些API统称为集合框架(Collection Framework),存放在jav.util包中,所以在使用时要导入java.util包
集合框架中存在多个容器,每一个容器对数据的存储方式都不同,这种存储方式称为:数据结构
v常用操作示例:
共性方法
import java.util.*;//使用了包中的方法,要先导包【小结】
class CollectionDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
//base_method();
//method_2();
method_get();
}
public static void method_get()
{
ArrayList a1 = new ArrayList();
a1.add("java1");
a1.add("java2");
a1.add("java3");
//接口型引用,通过集合中的方法
Iterator it = a1.iterator();//获取迭代器,用于取出集合中元素
while (it.hasNext())//若果仍有元素可迭代返回真,false则跳出循环
{
sop(it.next());
}
}
public static void method_2()//交集
{
ArrayList a1 = new ArrayList();
a1.add("java1");
a1.add("java2");
a1.add("java3");
ArrayList a2 = new ArrayList();
a2.add("java1");
a2.add("java8");
a2.add("java6");
//a1.retainAll(a2);//取交集,a1中只保留和a2中相同的元素
a1.removeAll(a2);//去交集,a1中只保留和a2中不同的元素
sop("a1="+a1);
sop("a2="+a2);
}
public static void base_method()
{
ArrayList a = new ArrayList();//创建一个集合容器,使用Collection接口的子类ArrayList
a.add("java1");//1、添加元素
a.add("java2");//add(Object obj);多态性
a.add("java3");
sop(a);//打印原集合
sop("size="+a.size());//2、获取元素个数
//a.remove("java3");//3、删除元素
//a.clear();// 清空集合
//4、判断元素
sop("java3是否存在:"+a.contains("java3"));
sop("集合是否为空 :"+a.isEmpty());
sop(a);
}
}
1,add方法参数为Object,多态性,以便于接受任意类型对象
2,集合中存储的都是对象的引用()
3,集合可以直接打印
Iterator接口,迭代器
集合中取出元素的方式
元素的取出方式定义在集合内部(内部类),以便于直接访问集合元素
每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都有共性内容判断hasNext()、取出.next();
向上抽取出来一个规则:Iterator;采用内部类的设计,通过一个对外提供的方法iterator(); 获取集合对象
Collection
|——List:元素是有序的,可以重复,因为该集合体系有索引;常见的子类对象:
|————ArrayList:数据结构是数组结构;特点:查询速度很快,但是增删稍慢;线程不同步
|————LinkedList:链表数据结构;特点:查询较慢,增删很快
|————Vector: 数组数据结构;线程同步;慢;被ArrayList替代了
——Set:元素是无序的,不能重复
List 特有方法,凡是可以操作角标的方法都是该体系特有方法
增
——add(index,element);
——addAll(index,Collection);
删
——remove(index);
改
——set(index,element);
查
——get(index):
——subList(from,to);
——listIterator();
——int indexOf(obj):获取指定元素的位置。
——ListIterator listIterator();
List集合特有的迭代器。ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。
List集合共性方法
import java.util.*;
class ListDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList a1 = new ArrayList();
a1.add("java1");
a1.add("java2");
a1.add("java3");
sop("原集合:"+a1);
ListIterator li = a1.listIterator();//更加强大
while (li.hasNext())
{
Object obj = li.next();
if (obj.equals("java2"))
//li.add("java007");//添加
li.set("java008");//修改
}
while (li.hasPrevious())//如果前面有元素则返回true
{
sop("pre:"+li.previous());//反向获取
}
/*Iterator it = a1.iterator();//迭代器,在迭代过程中,准备添加或删除元素
while (it.hasNext())//只能查,删,不能添加修改
{
Object obj = it.next();
if (obj.equals("java2"))
it.remove();//集合中持有的只是对象的引用,删除的也只是引用
sop("obj="+obj);//remove后对象并没有删除,所以obj的指向时仍有效
}*/
sop(a1);
}
public static void method()
{
ArrayList a1 = new ArrayList();
a1.add("java1");
a1.add("java2");
a1.add("java3");
sop("原集合:"+a1);
a1.add(2,"java08");//在指定位置添加元素
a1.remove(1);//删除指定角标元素
a1.set(2,"java007");//修改指定角标元素
sop("get(1)"+a1.get(1));//通过角标获取元素
sop(a1);
for (int x =0; x<a1.size() ;x++ )//获取所有元素
{
//sop("a1("+x+")="+a1.get(x));
}
Iterator it = a1.iterator();//迭代器
while (it.hasNext())
{
sop("next:"+it.next());
}
sop("index="+a1.indexOf("java007"));//通过indexOf获取对象的位置
List sub = a1.subList(0,2);//包含头不包含尾
sop("sub="+sub);
}
}
Vector中的枚举
elements
Enumeration en = v.elements();//枚举就是Vector特有的取出方式,枚举和迭代是一样的,被迭代器取代
while (en.hasMoreElements)
{
System.out.println(en.nextElement());
}
//因为枚举名称及方法的名称都过长,所以被迭代器取代了
LinkedList:特有方法
addFirst();
addLast();
getFirst();
getLast();
removeFirst();
removeLast();
如果列表为空,会抛出:NoSuchElementException
JDK1.6出现的替代方法
如果列表为空,会返回null
offerFirst();
offerLast();
peekFirst();
peekLast();
pollFirst();
pollLast();
LinkList操作
import java.util.*;
class LinkedListDemo
{
public static void sop (Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
LinkedList link = new LinkedList();
link.addFirst("java1");
link.addLast("java2");//在上一个元素尾部添加
link.addFirst("java3");//在上一个元素头部添加
link.addFirst("java4");
sop(link);
sop(link.getFirst());//获取链表头部元素,不删除
sop(link.getLast());//获取链表尾部元素
sop(link.removeFirst());//获取并删除元素,长度改变
sop(link.removeFirst());//可以重复出现
sop("size="+link.size());//获取链表长度
while (!link.isEmpty())
{
sop(link.removeFirst());
}
}
}
使用LinkedList模拟一个堆栈或队列数据结构
堆栈:先进后出 杯子
队列:先进先出 水管示例:
class DuiLie
{
private LinkedList link;
DuiLie()
{
link = new LinkedList();
}
public void myAdd(Object obj)
{
link.addFirst(obj);//
}
public Object myGet()
{
//return link.removeLast();//先进先出
return link.removeFirst();//后进先出
}
public boolean isNull()
{
return link.isEmpty();
}
}
取出ArrayList集合中的重复元素
public static ArrayList singleElement(ArrayList al)
{
ArrayList newAl = new ArrayList();//临时容器
Iterator it = al.iterator();//迭代数组al的元素
while (it.hasNext())
{
Object obj = it.next();
if (!newAl.contains(obj))//如果newAl中不包含该元素,则存入;如果重复则跳过
newAl.add(obj);
}
return newAl;//
}
将自定义对象作为元素存储到ArrayList集合中,并去除重复元素
比如:人对象,同姓名同年龄就视为同一个人;作为重复元素
思路:
1,对人进行描述,封装对象
2,定义容器,将人存入
3,取出
ArrayList操作
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public boolean equals(Object obj)//复写equals方法
{
if (!(obj instanceof Person))//健壮性判断;一元运算符!要加括号
return false;
Person p = (Person)obj;//类型向下强转
return this.name.equals(p.name) && this.age==p.age;//字符串的equals方法
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class ArrayListTest2
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("list001",23));//al.add(Object obj);多态性,不能直接访问子类Person特有方法
al.add(new Person("list002",22));//Object obj = new Person("list002",22);
al.add(new Person("list003",25));
al.add(new Person("list003",25));
al.add(new Person("list004",27));
al.add(new Person("list004",27));
//al = singleElement(al);
sop("remove 03:"+al.remove(new Person("list003",25)));//打印true说明在删除元素时要先equals判断是否存在
Iterator it = al.iterator();
while (it.hasNext())
{
Person p = (Person)it.next();//必须向下转型才能访问Person类的特有方法
sop(p.getName()+"..."+p.getAge());
}
}
public static ArrayList singleElement(ArrayList al)
{
ArrayList newAl = new ArrayList();//临时容器
Iterator it = al.iterator();//迭代数组al的元素
while (it.hasNext())
{
Object obj = it.next();
if (!newAl.contains(obj))//如果newAl中不包含该元素,则存入;如果重复则跳过
newAl.add(obj);//contains()调用的是equals方法
}
return newAl;//
}
}
【小结】
List元素判断元素是否相同,依据的是equals方法;ArrayList、LinkedList都是依赖于equals进行判断contains()的判断调用了equals方法,默认调用的是Object的equals方法,每一个元素的调次数 是由临时容器中的元素个数决定的;
String类中复写了equals,所以在判断时函数自动覆盖,不需要再复写;字符串对象(以及基本数据类型对象)都在类中复写了equals
而用对象做比较时,如果该类没有复写equals方法,默认调用的是Object的equals;判断的是对象的地址值(即是否同一个对象);而如果判断的是对象的属性是否重复,所以要复写equals方法,使contains调用时默认重载
在remove()对象时,也会调用equals()方法,如果该对象的类中复写了equals(),调用时覆盖,打印出true(如示例所示)
如果该类中没有复写equals() 则打印出false,因为调用的是Object中的equals方法
要重视运算符的作用,灵活运用!
实际使用中ArrayList用的比较多,因为一般数据查询的操作比较多