---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
一、集合框架
Java中的集合框架提供了一套设计优良的接口和类,成为集合API,它使程序员操作成批的数据或者对象元素极为方便,尤其是当用户事先不知道要存放数据的个数,或者需要一种比数组下标存取机制更灵活的方法时,就需要用到集合类。集合框架是程序开发过程中极其重要的一个概念,几乎每个项目都需要使用集合框架,熟练掌握其中的类和接口的使用方法可以大大提供程序开发的效率。集合框架结构结构由两颗接口树构成:第一棵树根节点为Collection接口,它定义了所有集合的基本操作,如添加,删除,遍历等。它的子接口Set、List等则提供了更加特殊的功能。第二棵树根节点为Map接口,和哈希表类似,保持的是键值对的集合,可以通过键来实现对值元素的快速访问。集合框架如下图示:
下面我将对集合框架中的接口和类进行详细的介绍。
二、Collection接口
Collection定义了所有属于集合的类都应该具有的通用方法,如下:
- boolean add(Object o) 插入单个对象,插入成功返回true,否则返回false
- boolean addAll(Collection c) 添加另外一个集合对象c中的所有对象,插入成功返回true,否则返回false
- Object[] toArray() 以数组的形式返回内容
- Object[] toArray() 以数组的形式返回内容,参数数组的类型就是所希望返回的类型
- Iterator iterator() 返回一个实现了Iterator接口的对象
- void clear() 清空所有对象
- boolean remove(Object o) 删除指定的对象,删除成功返回true,否则返回false
- boolean removeAll(Collection c) 删除c中所拥有的对象,删除成功返回true,否则返回false
- boolean retainAll(Collection c) 保留指定的对象,成功返回true,否则将返回false
- boolean contains(Object o) 检查是否包含指定的对象
- boolean containsAll(Collecion c) 检查是否包含c中所包含的对象
- boolean isEmpty() 判断集合是否为空
- int size() 获取集合中的对象个数
2.1 List接口
List:元素是有序的,元素可以重复,因为该集合体系有索引
List接口实现了三个子类:
ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快。但是增删速度慢,线程不同步
LinkedList: 底层使用的链表数据结构。增删速度快,查询速度慢
Vector:底层是数组数据结构,线程同步,被ArrayList替换了。
重要的是ArrayList和LinkedList,Vector已经被ArrayList取代了。
List接口在Collection接口的基础上有增加了一些特有方法,凡是可以操作角标的方法都是该体系特有的方法
增
add(index,eldment);
addAll(index,Collection);
删
remove(index);
改
set(index,element);
查
get(index);
subList(from,to);
listIterator();
对于List的方法操作示例如下:
public static void method() {
ArrayList a1=new ArrayList();
//1.添加元素。
a1.add("java01");
a1.add("java01");
a1.add("java03");
a1.add("java04");
//在指定位置添加元素
a1.add(1,"java09");
//删除指定位置的元素
a1.remove(2);
//修改元素
a1.set(2,"java007");
//查找,通过角标获取元素
a1.get(1);
//获取所有元素
for (int x=0;x<a1.size() ;x++ ) {
sop(a1.get(x));
}
//通过迭代器获取
Iterator it=a1.iterator();
while (it.hasNext()) {
sop(it.next());
}
//通过indexOf获取对象的位置
sop(a1.indexOf("java09"));
//获取子集
List sub=a1.subList(1,3);
}
来看一个ArrayList的例子:
例1:
/*
去除ArrayList中的重复元素
*/
import java.util.*;
class ArrayListTest {
public static void sop(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) {
ArrayList a1=new ArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java01");
a1.add("java03");
a1.add("java04");
sop(a1);
a1=singleElements(a1);
sop(a1);
}
public static ArrayList singleElements(ArrayList list) {
ArrayList newList= new ArrayList();
Iterator it =list.iterator();
while (it.hasNext()) {
Object obj=it.next();
if (!newList.contains(obj)) {
newList.add(obj);
}
}
return newList;
}
}
例2:
将自定义对象作为元素存到ArrayList集合中,并去除重复元素
比如:存入对象 ,同姓名同年龄的,视为同一个人,为重复元素
/*
思路:
1、对人的描述,将数据封装进对象
2、定义容器,将人进行存储
3、取出
List集合判断元素是否相同,根据元素的equals方法
*/
import java.util.*;
class Person {
private String name;
private int age;
Person(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean equals(Object obj) {//List集合判断元素是否相同,根据元素的equals方法,为什么不复写contains方法
if(!(obj instanceof Person)) {
return false;
}
Person p =(Person)obj;
return (this.name.equals(p.name))&&(this.age==p.age);
}
}
class ArrayListTest2{
public static void sop(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) {
ArrayList a1=new ArrayList();
a1.add(new Person("lisi01",30));//Object obj;obj=Person();//多态
a1.add(new Person("lisi02",31));
a1.add(new Person("lisi03",32));
a1.add(new Person("lisi03",32));
a1.add(new Person("lisi04",33));
a1.add(new Person("lisi05",34));
a1.add(new Person("lisi05",34));
a1=singleElements(a1);
//sop(a1);
sop(a1.remove(new Person("lisi01",30)));//remove调用的也是底层的equals
Iterator it=a1.iterator();
while (it.hasNext()) {
Person p=(Person)it.next();//向下转型
sop(p.getName()+"..."+p.getAge());
}
}
public static ArrayList singleElements(ArrayList list) {
ArrayList newList= new ArrayList();
Iterator it =list.iterator();
while (it.hasNext()) {
Object obj=it.next();
// Person p=(Person)it.next();
if (!newList.contains(obj)) {
newList.add(obj);
}
}
return newList;
}
}
在这里需强调一下:List集合判断元素是否相同依靠的是equals()方法;如果要自定义比较方式,需让待存元素具有排序方式,就需要复写equals()方法。
LinkedList: 底层使用的链表数据结构。增删速度快,查询速度慢
LinkedList:特有方法:
addFirst();//头插
addLast();//尾插
removeFirst();
removeLast();
获取元素后元素被删除
如果链表中没有元素,那么抛出NoSuchElementException异常
但是升级后 返回null
JDK1.6出现了替代方法
offerFirst();
offerLast();
添加元素
peerFirst();
peerLast();
获取元素,没有元素,返回null
pollFirst();
pollLast();
获取元素后元素被删除,没有元素,返回null
例:
使用LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出 First In Last Out 如同一个杯子
队列:先进先出 Fisst In First Out 如同一个杯子
import java.util.*;
class MyQueue {
private LinkedList link;
MyQueue() {
link=new LinkedList();
}
public void myAdd(Object obj) {
link.addFirst(obj);
}
public Object myGet() {
return link.removeLast();
}
public boolean myIsNull() {
return link.isEmpty();
}
}
class LinkedListTest {
public static void main(String[] args) {
MyQueue q=MyQueue();
q.myAdd("java01");
q.myAdd("java02");
q.myAdd("java03");
q.myAdd("java04");
while (!q.myIsNull) {
System.out.println(q.myGet());
}
}
}
2.2 Set集合
Set集合的特点是:元素是无序的,元素不可以重复,而且Set集合的方法和Collection保持一致
Set接口下有两个子类:
HashSet和TreeSet
HashSet: 底层数据结构是哈希表
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成的,如果元素的HashCode值相同,才会判断equals是否相同如果元素的HashCode值不相同,不会调用equals
例:
import java.util.*;
class Person {
private String name;
private int age;
Person(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int hashCode() {
System.out.println("name="+this.name+"..hashCode="+name.hashCode());//显示过程
return name.hashCode()+age;
}
public boolean equals(Object obj) {
if(!(obj instanceof Person)) {
return false;
}
Person p =(Person)obj;
System.out.println(this.name+"...."+p.name);
return (this.name.equals(p.name))&&(this.age==p.age);
}
}
class HashSetDemo {
public static void sop(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) {
HashSet a1=new HashSet();
a1.add(new Person("lisi01",30));//Object obj;obj=Person();//多态
a1.add(new Person("lisi02",31));
a1.add(new Person("lisi03",32));
a1.add(new Person("lisi03",32));
a1.add(new Person("lisi04",33));
a1.add(new Person("lisi05",34));
a1.add(new Person("lisi05",34));
sop(a1.contains(new Person("lisi06",35)));
Iterator it=a1.iterator();
while (it.hasNext()) {
Person p=(Person)it.next();//向下转型
sop(p.getName()+"..."+p.getAge());
}
}
}
TreeSet:可以对Set集合中的元素进行自然排序,底层数据结构是二叉树
保证元素唯一性的依据:compareTo方法return 0;
TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然排序,或者叫做默认顺序。
例:
需求:往Set集合中存储自定义对象学生,按照年龄进行排序
import java.util.*;
class Student implements Comparable{
private String name;
private int age;
Student(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
/**/
public int hashCode() {
System.out.println("name="+this.name+"..hashCode="+name.hashCode());//显示过程
return name.hashCode()+age;
}
public int compareTo(Object obj) {
/*
return 1;//怎么存进去的怎么取出来
*/
if(!(obj instanceof Student)) {
throw new RuntimeException("不是学生对象");
}
Student stu =(Student)obj;
System.out.println(this.age+"...."+stu.age);
if (this.age>stu.age) {
return 1;
}
if (this.age==stu.age) {
return this.name.compareTo(stu.name);
}
return -1;
}
}
class TreeSetDemo {
public static void sop(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) {
TreeSet a1=new TreeSet();
a1.add(new Student("lisi01",30));//Object obj;obj=Student();//多态
a1.add(new Student("lisi02",31));
a1.add(new Student("lisi03",32));
a1.add(new Student("lisi03",32));
a1.add(new Student("aisi04",33));
a1.add(new Student("lisi05",34));
a1.add(new Student("risi05",34));
//sop(a1.contains(new Student("lisi06",35)));
Iterator it=a1.iterator();
while (it.hasNext()) {
Student p=(Student)it.next();//向下转型
sop(p.getName()+"..."+p.getAge());
}
}
}
TreeSet的第二种排序方式
当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式:构造函数
例:自定义比较器,按照名字排序
import java.util.*;
class TreeSetDemo2 {
public static void sop(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) {
TreeSet a1=new TreeSet(new MyCompare());//使用自定义的比较器
a1.add(new Student("lisi01",30));
a1.add(new Student("lisi02",31));
a1.add(new Student("lisi03",32));
a1.add(new Student("lisi03",32));
a1.add(new Student("aisi04",33));
a1.add(new Student("lisi05",34));
a1.add(new Student("risi05",34));
Iterator it=a1.iterator();
while (it.hasNext()) {
Student p=(Student)it.next();//向下转型
sop(p.getName()+"..."+p.getAge());
}
}
}
class Student implements Comparable{
private String name;
private int age;
Student(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int hashCode() {
System.out.println("name="+this.name+"..hashCode="+name.hashCode());//显示过程
return name.hashCode()+age;
}
public int compareTo(Object obj) {
return 1;//怎么存进去的怎么取出来
/*
if(!(obj instanceof Student)) {
throw new RuntimeException("不是学生对象");
}
Student stu =(Student)obj;
System.out.println(this.age+"...."+stu.age);
if (this.age>stu.age) {
return 1;
}
if (this.age==stu.age) {
return this.name.compareTo(stu.name);
}
return -1; */
}
}
class MyCompare implements Comparator {//自定义比较器
public int compare(Object o1,Object o2) {
Student s1=(Student)o1;
Student s2=(Student)o2;
int num =s1.getName().compareTo(s2.getName());
if (num==0) {
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
/*
if (num==0) {
if (s1.getAge()>s2.getAge()) {
return 1;
}
if (s1.getAge()==s2.getAge()) {
return 0;
}
return -1;
}
}*/
}
return num;
}
}
三、Map
Map集合:该集合存储键值对。一对一对的往里存,而且要保证键的唯一性。
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的。jdk1.0,效率低
|--HashMap:底层是哈希表数据结构,允许使用null键null值,该集合是不同步的,jdk1.2,效率高
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用Map集合中的键进行排序
重点是HashMap和TreeMap。
关于Map集合的操作有:
1,添加
V put(K key, V value)
void putAll(Map<? extends K,? extends V> m)
2,删除
void clear()
V remove(Object key)
3,判断
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
4,获取
int size()
V get(Object key)
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()
Set<K> keySet()
常用方法操作演示:
import java.util.*;
class MapDemo01 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
//put也是有返回值的,返回的对应键的值,
//添加元素时,如果出现添加相同的键,那么后添加的值覆盖原有键对应的值。
System.out.println("put:"+map.put("01","zhangshan01"));
System.out.println("put:"+map.put("01","wangwu01"));
map.put("02","zhangshan02");
map.put("03","zhangshan03");
System.out.println("containsKey:"+map.containsKey("02"));
//获取map集合中所有的值
Collection<String> coll=map.values();
System.out.println(coll);
System.out.println(map);
}
}
需要重点掌握的是后两种方法,前面的一些方法都是基础操作。
map集合的两种取出方式;
1、Set<k> keySet(): 将Map中所有的键存入到Set集合,因为Set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。
例:
import java.util.*;
class MapDemo02 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("02","zhangshan02");
map.put("03","zhangshan03");
map.put("01","zhangshan01");
map.put("04","zhangshan04");
//先获取Map集合的所有键Set集合,keySet();
Set<String> keySet=map.keySet();
//有了Set集合就可以获取迭代器
Iterator<String> it=keySet.iterator();
while (it.hasNext()) {
String key=it.next();
System.out.println("key:"+key+"...value:"+map.get(key));//通过Map中的get(key);获取value
}
}
}
2、Set<Map.Entry<K,V>> entrySet() :将Map集合中的映射关系存入到了Set集合中,而这个关系的数据类型就是:Map.Entry
import java.util.*;
class MapDemo02 {
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("02","zhangshan02");
map.put("03","zhangshan03");
map.put("01","zhangshan01");
map.put("04","zhangshan04");
//将Map集合中的映射关系取出 ,存入到Set集合中
Set<Map.Entry<String,String>> entruSet=map.entrySet();
Iterator<Map.Entry<String,String>> it=entry.itetator();
while (it.hasNext()) {
Map.Entry<String,String> me=it.next();
String key=me.getKey();
String value=me.getValue();
System.out.println(key+".."+value);
}
}
}
下面看几道例题:
例1:
/*
每一个学生都有对应的归属地。
学生Student, 地址String
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性。
解题思路:
1、描述学生。
2、定义Map容器,将学生作为键,地址作为值,存入。
3、获取Map集合中的元素。
*/
import java.util.*;
class Student implements Comparable<Student> {
private String name;
private int age;
Student(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int compareTo(Student s) {
int num=new Integer(this.age).compareTo(new Integer(s.age));
if (num==0) {
return this.name.compareTo(s.name);
}
return num;
}
public int hashCOde() {
return name.hashCode()+age*21;
}
public boolean equals(Object obj) {
if (!(obj instanceof Student)) {
throw new ClassCastException("类型不匹配");
}
Student s=(Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
public String toString() {
return name+"年龄"+age;
}
}
class MapTest03 {
public static void main(String[] args) {
HashMap<Student,String> map=new HashMap<Student,String>();
map.put(new Student("lisi1",21),"北京");
map.put(new Student("lisi2",22),"天津");
map.put(new Student("lisi3",23),"南京");
map.put(new Student("lisi4",24),"上海");
//第一种取出方式
Set<Student> s=map.keySet();
Iterator<Student> it=s.iterator();
while (it.hasNext()) {
Student key=it.next();
String add=map.get(key);
System.out.println(key+".."+add);
}
//第二种取出方式
Set<Map.Entry<Student,String>> ss=map.entrySet();
Iterator<Map.Entry<Student,String>> itor=ss.iterator();
while (itor.hasNext()) {
Map.Entry<Student,String> stuAdd=itor.next();
Student key=stuAdd.getKey();
String add_=stuAdd.getValue();
System.out.println(key+"....."+add_);
}
}
}
例2:
/*
需求:对学生对象的年龄进行升序排序。
因为数据时一键值对形式存在的,
所以要使用可以排序的Map集合。TreeMap
*/
import java.util.*;
class Student implements Comparable<Student> {
private String name;
private int age;
Student(String name,int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int compareTo(Student s) {//按年龄排
int num=new Integer(this.age).compareTo(new Integer(s.age));
if (num==0) {
return this.name.compareTo(s.name);
}
return num;
}
public int hashCOde() {
return name.hashCode()+age*21;
}
public boolean equals(Object obj) {
if (!(obj instanceof Student)) {
throw new ClassCastException("类型不匹配");
}
Student s=(Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
public String toString() {
return name+"年龄"+age;
}
}
//自定义比较器,按姓名排
class StuNameComparator implements Comparator<Student> {
public int compare(Student s1,Student s2) {
int num=s1.getName().compareTo(s2.getName());
if (num==0) {
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return num;
}
}
class MapTest04 {
public static void main(String[] args) {
TreeMap<Student,String> map=new TreeMap<Student,String>(new StuNameComparator());
map.put(new Student("lisi1",25),"北京");
map.put(new Student("lisi2",22),"天津");
map.put(new Student("lisi3",23),"南京");
map.put(new Student("lisi4",24),"上海");
Set<Map.Entry<Student,String>> ss=map.entrySet();
Iterator<Map.Entry<Student,String>> itor=ss.iterator();
while (itor.hasNext()) {
Map.Entry<Student,String> stuAdd=itor.next();
Student key=stuAdd.getKey();
String add_=stuAdd.getValue();
System.out.println(key+"....."+add_);
}
}
}
例3:
/*
练习:获取该字符串“ajlkgijoikghgafgash”中字母出现的次数
*/
import java.util.*;
class TreeMapDemo05 {
public static void main(String[] args) {
String s=getCount("alkjfognskadkfalkd");
System.out.println(s);
}
public static String getCount(String str) {
char[] ch=str.toCharArray();
TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
for (int i=0;i<ch.length ;i++ ) {
if (!(ch[i]>='a'&&ch[i]<='z'||ch[i]>='A'&&ch[i]<='Z')) {
continue;
}
Integer value= tm.get(ch[i]);
if (value==null) {
tm.put(ch[i],1);
}
else {
tm.put(ch[i],value+1);
}
}
StringBuffer sb=new StringBuffer();
Set<Map.Entry<Character,Integer>> entry=tm.entrySet();
Iterator<Map.Entry<Character,Integer>> it=entry.iterator();
while (it.hasNext()) {
Map.Entry<Character,Integer> t=it.next();
char key=t.getKey();
int value=t.getValue();
sb.append(key+"("+value+")");
}
return sb.toString();
}
}
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------