一、集合类概述
Java的util保重提供了一些集合类,这些集合类又称为容器,一提到容器就会想到数组,可是集合跟数组是不同的,他们的不同之处是,数组的长度是固定的,而集合的长度是可变的,数组用来存放基本类型的数据,而集合除了这些之外还可以存放对象引用。常用的集合有List集合,Set集合,Map集合,其中List和Set集合继承了Collection接口,各个接口还提供了不同的类。集合类的关系图如下。
二、Collection接口
Collection接口是层次结构中的根接口。构成Collection的单位称为元素。Collection接口通常不能直接使用,但是该接口提供了添加元素,删除元素,管理数据的方法。由于List接口和 Set接口都继承了Collection接口,因此这些方法对Set和List都是通用的。
1、常见的操作方法如下:
add(E e) 确保此 collection 包含指定的元素(可选操作)。addAll(Collection<? extends E> c) 将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。clear() 移除此 collection 中的所有元素(可选操作)。contains(Object o) 如果此 collection 包含指定的元素,则返回 true。containsAll(Collection<?> c) 如果此 collection 包含指定 collection 中的所有元素,则返回 true。equals(Object o) 比较此 collection 与指定对象是否相等。hashCode() 返回此 collection 的哈希码值。isEmpty() 如果此 collection 不包含元素,则返回 true。iterator() 返回在此 collection 的元素上进行迭代的迭代器。remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。removeAll(Collection<?> c) 移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。retainAll(Collection<?> c) 仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。size() 返回此 collection 中的元素数。toArray() 返回包含此 collection 中所有元素的数组。
toArray(T[] a) 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
2、迭代器的使用
迭代是在集合中遍历元素的方式。因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。通常遍历集合,都是通过迭代器Iterate类实现的。Collection接口中的iterator()方法可以返回Collection进行迭代的迭代器。
Iterate的方法摘要如下:
hasNext() 返回值是 boolean 类型 如果仍有元素可以迭代,则返回 true。
next() 返回迭代的下一个元素。
remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
迭代器的两种使用方式:
1)、for(Iterator iter = iterator();iter.hasNext(); )
{
System.out.println(iter.next());
}
2)、Iterator iter = l.iterator();
while(iter.hasNext())
{
System.out.println(iter.next());
}
三、List集合
List集合中的元素是允许重复的,切元素是有序的,这里的有序是指存取的顺序是一致的。并且该集合体系中索引。
List:特有的常见方法。
有一个共性特点就是都可以操作角标。
1、添加
add(index,element);
addAll(index,collection);
2、删除
remove(index);
3、修改
set(index,element);
4、获取:
get(index);
indexOf(object);
lastIndexOf(object);
subList(from,to);
List集合可以完成对元素的增删改查。
List接口的实现类:
List接口的类有Arraylist Linklist Vector
ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
ArrayList的示例:
import java.util.*;
class ArrayListDemo
{
public static void main(String[] args)
{
List list=new ArrayList();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
int i=(int )(Math.random()*(list.size()-1));
System.out.println("随机获得的元素是"+list.get(i));
System.out.println("原始数组的元素是"+list);
list.remove(2);
System.out.println("移除索引值为2的元素后,数组中的元素为");
Iterator it1 = list.iterator();
while(it1.hasNext())
{
String str=(String)it1.next();
System.out.println(str);
}
}
}
运行结果为:
由结果可以看出,集合跟数组相同,集合的索引号也是从0开始。
LinkList的示例:
import java.util.*;
public class LinkedListDemo {
public static void main(String[] args)
{
LinkedList list=new LinkedList();
LinkedList list1=new LinkedList();
list.addFirst("java01");
list.addFirst("java02");
list.addFirst("java03");
list.addFirst("java04");
list1.add("java01");
list1.add("java02");
list1.add("java03");
list1.add("java04");
Iterator it1=list.iterator();
System.out.println(list);
System.out.println(list1);
while(it1.hasNext())
{
System.out.println(it1.next());
}
list.removeAll(list);
if(!list.isEmpty())
{
System.out.println("集合不为空");
}
else{
System.out.println("空集合");
}
}
}
运行结果为:
三、Set集合
Set集合中的对象不按照特定的方式排序,只是简单的把对象加入集合中,但是Set集合中不能包含重复的元素或对象,Set继承了Collection接口,所以包含Collection中的所有方法。
Set接口的实现类
HashSet:内部数据结构是哈希表,是不同步的。
TreeSet:可以对Set集合中的元素进行排序,是不同步的。
1、HashSet
HashSet的线程不安全但是,存取速度很快。
HashSet确定元素的唯一性是通过hashCode和equals方法来实现的。原理是如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。
示例:
import java.util.*;
import org.omg.CORBA.CTX_RESTRICT_SCOPE;
class Student
{
private String name;
private int age;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public class HashSetDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet hs=new HashSet();
hs.add(new Student("zhangsan", 20));
hs.add(new Student("zhaoliu", 22));
hs.add(new Student("wangwu", 23));
hs.add(new Student("hetong", 24));
hs.add(new Student("zhangsan", 21));
Iterator it=hs.iterator();
while(it.hasNext())
{
Student st=(Student)it.next();
System.out.println(st.getName()+"............."+st.getAge());
}
}
}
运行结果:
当最后以后数据的年龄为21时,数据可以添加进去,当为20时就不能添加进去
2、TreeSet
TreeSet的特点:
1、底层结构是二叉树结构
2、可以通过比较器对TreeSet类实现的集合中的对象进行排序,排序的方式有两种,第一种是让元素自身具备比较功能,元素就需要实现Comparable接口,覆盖compareTo方法。如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?可以使用TreeSet集合第二种排序方式:让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
当主要条件排序一样时,就要考虑次要条件。
TreeSet的第一种排序方式示例(实现Comparable接口):
import java.util.*;
class Student1 implements Comparable{
private String name;
private int age;
public Student1(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Student1 stu= (Student1)o;
//当主要条件相同时要判断次要条件,字符串利用自带的比较函数
return age>stu.age?1:(age==stu.age?(name.compareTo(stu.name)):-1);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class TreeSetDemo1 {
public static void main(String[] args) {
TreeSet ts=new TreeSet();
ts.add(new Student1("zhangsan",18));
ts.add(new Student1("zhangsan1",18));
ts.add(new Student1("zhangsan",20));
ts.add(new Student1("zhangsan",19));
Iterator it=ts.iterator();
while(it.hasNext())
{
Student1 s= (Student1)it.next();
System.out.println(s.getName()+"..........."+s.getAge());
}
}
}
运行结果:
TreeSet的第二种排序方式示例(实现Comparator接口):
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
class Student2 implements Comparable{
private String name;
private int age;
public Student2(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Student2 stu= (Student2)o;
//当主要条件相同时要判断次要条件,字符串利用自带的比较函数
return age>stu.age?1:(age==stu.age?(name.compareTo(stu.name)):-1);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class ComparatorByName implements Comparator{
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
Student2 s1=(Student2)o1;
Student2 s2=(Student2)o2;
int temp=s1.getName().compareTo(s2.getName());
return temp==0?s1.getAge()-s2.getAge():temp;
}
}
public class TreeSetDemo2 {
public static void main(String[] args) {
TreeSet ts=new TreeSet(new ComparatorByName());
ts.add(new Student2("zhangsan",18));
ts.add(new Student2("zhangsan1",18));
ts.add(new Student2("zhangsan",20));
ts.add(new Student2("zhangsan",19));
Iterator it=ts.iterator();
while(it.hasNext())
{
Student2 s= (Student2)it.next();
System.out.println(s.getName()+"..........."+s.getAge());
}
}
}
运行结果是:
三、Map集合
1、Map集合的概述
Map集合没有继承Collection接口,其提供的是key到value的映射。Map中不能包含相同的key,每一个key只能映射到一个value。key中还决定了存储对象在映射中的存储位置,但不是由key对象本身决定的,而是通过一种”散列技术“进行处理,产生一个散列码的整数值,散列码通常用左一个偏移量,该偏移量对应分配给映射的内存区域的起始位置,从而确定存储对象在映射中的存储位置。
2、Map集合中常用的方法
clear() 从此映射中移除所有映射关系(可选操作)。
containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。
containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
equals(Object o) 比较指定的对象与此映射是否相等。
get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
hashCode() 返回此映射的哈希码值。
isEmpty() 如果此映射未包含键-值映射关系,则返回 true。
put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。
putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。
remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
size() 返回此映射中的键-值映射关系数。
values() 返回此映射中包含的值的 Collection 集合。
3、Map集合中的子类
Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。效率低。
HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。效率高。
TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
Map和Set很像。其实Set底层就是使用了Map集合。
4、Map集合的两种取值方式:
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 集合。
原理是将Map中所以的键存入到Set集合。因为Set具备迭代器。所以可以通过迭代方式取出所以键的值,再通过get方法。获取每一个键对应的值。
Set<K> keySet() 返回此映射中包含的键的 Set 集合。
原理是将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是:Map.Entry。其实,Entry也是一个接口,它是Map接口中的一个内部接口。
下面就两个取值方式做出示例:
(1)Set<K> keySet() 方式示例:
import java.util.*;
class Student3 implements Comparable{
private String name;
private int age;
public Student3(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Student3 stu= (Student3)o;
//当主要条件相同时要判断次要条件,字符串利用自带的比较函数
return age>stu.age?1:(age==stu.age?(name.compareTo(stu.name)):-1);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return name+"........"+age;
}
}
public class HashMapDemo {
public static void main(String[] args) {
HashMap<Student3,String> ts=new HashMap();
Student3 stu1=new Student3("zhangsan",18);
Student3 stu2=new Student3("zhangsan1",18);
Student3 stu3=new Student3("zhangsan",20);
Student3 stu4=new Student3("zhangsan",19);
ts.put(stu1,"beijing");
ts.put(stu2,"tianjin");
ts.put(stu3,"chongqing");
ts.put(stu4,"shanghai");
keySet(ts);
}
private static void keySet(HashMap<Student3, String> ts) {
// TODO Auto-generated method stub
Iterator<Student3> it=ts.keySet().iterator();
while(it.hasNext())
{
Student3 s=it.next();
String address=ts.get(s);
System.out.println(s+":"+address);
}
}
}
运行结果为:
(2)Set<Map.Entry<K,V>> entrySet() 方式示例:
取出方式的主要代码是:
private static void entrySet(HashMap<Student3, String> ts) {
// TODO Auto-generated method stub
Iterator<Map.Entry<Student3, String>> it=ts.entrySet().iterator();
while(it.hasNext())
{
Map.Entry<Student3, String> me=it.next();
Student3 s=me.getKey();
String address=me.getValue();
System.out.println(s+":::"+address);
}
}
运行结果与上示例结果一样。