------- android培训、java培训、期待与您交流! ----------
集合
1. 概述:
集合是用于给对象存储的容器,在以往的情况里,对象可以存储在数组里,但是数组是个有界集合,即其容量有限。如果在对象的存储中并不能确定对象的数量,或想要存储的对象数量没有上限,这个时候定义一个非常大的数组是不可取的,这时就要用到集合类。
2.Collection
集合类的顶层接口是Collection类在学习一个大类的时候我们首先要从这个类的顶层接口俯瞰,在顶层接口中能看到这个类中所有子类的共有方法。集合类的构成:
Collection类中几个重要的方法:
1. 增加
boolean add(E e):添加一个元素。如果此 collection 由于调用而发生更改,则返回 true。(如果此 collection 不允许有重复元素,并且已经包含了指定的元素,则返回 false。)
2.删除
boolean remove(Object o):从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。如果此 collection 包含指定的元素(或者此 collection 由于调用而发生更改),则返回 true 。
boolean removeAll(Collection<?> c):移除此 collection 中那些也包含在指定 collection 中的所有元素。此调用返回后,collection 中将不包含任何与指定 collection 相同的元素。
void clear():移除此 collection 中的所有元素。此Collection不支持该方法,则抛出一个异常UnsupportedOperationException。
3. 查找
boolean contains(Object o):如果此 collection 包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c):如果此 collection 包含指定 collection 中的所有元素,则返回 true。
boolean isEmpty():如果此 collection 不包含元素,则返回 true。
4.获取
Iterator<E> iterator():返回在此 collection 的元素上进行迭代的迭代器。
Object[] toArray()/<T> T[] toArray(T[] a):返回包含此 collection 中所有元素的数组。
其中Iterator<E> iterator()返回的是一个迭代器,该迭代器是依赖于具体容器的,迭代器是容器的内部类。因为每个容器的存储数据的结构不同,Iterator在每个容器中的实现方式都不一样。
Iterator类有两个常用方法:boolean hasNext():如果存在下一个元素则返回true。
<E> next():返回下一个迭代器中的元素。
public class IteratorTest {
public static void main(String[] args) {
Collection<String> al = new ArrayList<String>() ;
al.add("a");
al.add("b");
al.add("1");
al.add("2");
System.out.println(al);
//使用Iterator迭代器遍历集合中的元素
Iterator<String> iterator = al.iterator();
while(iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
}
}
2. List
List接口可以对列表中每个元素的插入位置进行精确地控制。可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。因为其底层是数组结构,每一个元素都拥有一个角标索引,且允许元素重复。除去Collection中几个重复的方法外,List还有几个自己特有的常用方法:
1.查找
boolean equals(Object o):比较指定的对象与列表是否相等。
int lastIndexOf(Object o):返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
2.获取
E get(int index):返回列表中指定位置的元素。由于List是数组属性的,可以使用索引精确的得到指定位置的元素。
int lastIndexOf(Object o):返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
ListIterator<E> listIterator():返回此列表元素的列表迭代器(按适当顺序)。
3.修改
E set(int index, E element):同样,也可以使用索引精确替换指定位置的元素。
E remove(int index):移除列表中指定位置的元素(可选操作)。将所有的后续元素向左移动(将其索引减 1)。返回从列表中移除的元素。
注意到ListIterator<E> listIterator()返回的是一个ListIterator对象,这个对象是List中特有的Iterator对象。
ListIterator对象有几个相比Iterator不同的常用方法:
void add(E e) :将指定的元素插入列表(可选操作)。该元素直接插入到 next 返回的下一个元素的前面(如果有)。
E previous():返回列表中的前一个元素。
List接口下有两个常用的可实例化的子类:ArrayList和LinkedList他们的区别如下:
ArrayLiat: 内部是数组结构数据,不是同步的,替代Vector,查询速度很快。
LinkedList :内部是链表结构数据,不是同步的。增删元素很快,查询慢。
值得注意的是List还有一个子类Vector其内部是数组结构数据,是同步的。其增删、查询速度都很慢。由于其速度慢的特性,现在已经被ArrayList和LinkedList取代。
Vector类中有一个方法public Enumeration<E> elements(),该方法返回的是一个枚举的对象,枚举的使用方法和Iterator类似。
boolean hasMoreElements():测试此枚举是否包含更多的元素。
E nextElement():如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。
public class VectorTest {
public static void main(String[] args) {
Vector<String> vector = new Vector<String>() ;
vector.add("b") ;
vector.add("c") ;
vector.add("d") ;
vector.add("e") ;
//使用Enumeration 遍历集合
Enumeration<String> enumeration = v.elements();
while(enumeration.hasMoreElements()){
System.out.print(enumeration.nextElement()+" ");
}
}
}
ArrayList中的方法和List中大同小异,其中有一个方法是ArrayList中特有的:
protected void removeRange(int fromIndex,int toIndex):移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。向左移动所有后续元素(减小其索引)。
LinkedList则有很多自己特有的方法:
1. 增加
public void addFirst(E e):将指定元素插入此列表的开头。
public void addLast(E e):将指定元素添加到此列表的结尾。等同于add方法。
2. 获取
public E getLast():获取最后一个元素。
class MyStack<T>{
private LinkedList<T> list ;
public MyStack()
{
list = new LinkedList<T>();
}
//进栈方法,每次进来的元素只能添加在末尾
public void put(T t)
{
list.addLast(t);
}
//出栈方法,每次只能从末尾移除
public T get()
{
return list.removeLast();
}
public boolean isEmpty()
{
return list.isEmpty();
}
public String toString()
{
return list.toString();
}
}
3. Set
Set中元素是不可以重复的,是无序的;
Set下有两个常用可以实例化的子类HashSet和TreeSet
- HashSet底层结构是哈希表,HashSet通过先比较元素的HashCode来初步确认元素是否相同,若元素的HashCode相同,再通过调用元素的equals方法来确定元素是否相同。
- Tree的底层结构是二叉树结构,TreeSet可以通过自己的比较方法来对元素排序。TreeSet对元素的比较方法有两种。一是调用元素自身的compareTo方法,当然,当一个元素要具备compareTo方法时才具备比较性。让一个元素具备比较性必须让其实现compareable接口并复写compareTo方法。TreeSet对元素比较的方法之二是构造一个比较器,并将该比较器传入TreeSet的构造函数中。TreeSet根据比较方式的返回值来确定元素的顺序。当返回值为0时就认为两个元素是相同的。
下面是一个利用HashSet去除数组中重复数据的例子:
import java.util.*;
/*
* 需求:去除重复元素,要求对于不同的元素都能有效去除
* 思路:使用HashSet的去重复功能
*
*
* HashSet先判断元素的HashCode是否一致,若不一致则视为不同元素;若一致则再判断元素的equals方法
* 若返回false则视为不同的元素;
* */
class person
{
private String name;
private int age;
person(Stringname,int age)
{
this.name =name;
this.age=age;
}
public void getInfo()
{
System.out.println("name:"+name+" age:"+age);
}
public boolean equals(Object per)//复写object类中的equals方法,成为元素自己判断异同的独有方法;
{
if(per instanceof person)
return this.name==((person)per).name&&this.age==((person)per).age;
else
return false;
}
public int hashCode()//复写object类中的hashCode方法,用于给HashSet做第一步的判断;
{
return name.hashCode()+age*13;
}
}
public classGetOutRepeatElement {
public static void main(String[] args) {
// TODO Auto-generated method stub
persons1=new person("zhangsan",21);
persons2=new person("wangwu",21);
persons3=new person("zhangsan",23);
persons4=new person("zhangsan",21);
person[]per={s1,s2,s3,s4};
//---------------------HashSet方法-----------------------//
HashSet<person>has=newHashSet<person>();
for(int i=0;i<per.length;i++)
{
if(!has.contains(per[i]))
{
has.add(per[i]);
}
}
Iterator<person>it_2=has.iterator();
System.out.println("HashSet结果:");
while(it_2.hasNext())
{
it_2.next().getInfo();
}
}
}
排序结果是
HashSet结果:
name:zhangsan age:23
name:zhangsan age:21
name:wangwu age:21
下面是一个利用TreeSet两种排序方式排序的例子:
import java.util.*;
/**
* TreeSet排序问题:TreeSet可以对元素进行排序,依据的是对象的CompareTo方法,当对象不具备此方法时
* 不具备可比性,但是可以使对象的类实现compaeable接口并复写其compareto方法达到实现可比性的方法
*
*
* 另外,TreeSet还可以通过构造comparator 比较器来实现比较方法,当两种方法共存时比较器方法更优先
*
* * */
class preson_2 implements Comparable<preson_2>
//实现了泛型接口可以在复写该泛型接口的方法时指定对象类型
{
private String name;
private int age;
preson_2(Stringname,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public void getInfo()
{
System.out.println("Name:"+name+" Age:"+age);
}
public int compareTo(preson_2 s)
//注意Comparable<E>接口的方法不是泛型的,不能使用泛型方法
{
int num=this.age-s.age;
if(num==0)
{
return this.name.toString().compareTo(s.name.toString());
}
return num;
}
}
//同理Comparator<E>接口的方法不是泛型的,复写不能使用泛型方法
//建立一个比较器,该类必须实现comparator<E>并复写compare方法
class compass implements Comparator<preson_2>
{
public int compare(preson_2 o1, preson_2 o2)
{
int num=o1.getAge()-o2.getAge();
int nae=o1.getName().compareTo(o2.getName());
if(nae==0)
{
return num;
}
return nae;
}
}
public classTreeSetDemo {
public static void main(String[] args) {
TreeSet<preson_2>ts=newTreeSet<preson_2>();
//建立TreeSet并装载已建立的比较器
TreeSet<preson_2>ts2=newTreeSet<preson_2>(new compass());
preson_2s1=new preson_2("zhangsan1",21);
preson_2s2=new preson_2("zhangsan2",22);
preson_2s3=new preson_2("zhangsan3",23);
preson_2s4=new preson_2("zhangsan1",21);
preson_2s5=new preson_2("zhangsan2",24);
preson_2[]per={s1,s2,s3,s4,s5};
for(int i=0;i<per.length;i++)
{
if(!ts.contains(per[i]))
{
ts.add(per[i]);
}
}
Iterator<preson_2>it = ts.iterator();
System.out.println("comparable方法:");
while(it.hasNext())
{
(it.next()).getInfo();
}
for(int i=0;i<per.length;i++)
{
if(!ts2.contains(per[i]))
{
ts2.add(per[i]);
}
}
Iterator<preson_2>it2= ts2.iterator();
System.out.println("comparator方法:");
while(it2.hasNext())
{
(it2.next()).getInfo();
}
}
}
排序结果是:
comparable方法:
Name:zhangsan1 Age:21
Name:zhangsan2 Age:22
Name:zhangsan3 Age:23
Name:zhangsan2 Age:24
comparator方法:
Name:zhangsan1 Age:21
Name:zhangsan2 Age:22
Name:zhangsan2 Age:24
Name:zhangsan3 Age:23
总结:List集合是有序的,可以利用其索引快速查找和修改指定位置的元素,其允许存储重复元素。
Set集合是无序的,,存入的元素不可以重复。其子类TreeSet可以通过实现compareTo方法和构造比较器来让元素排序