本文共 8264 字,大约阅读时间需要 27 分钟。
1.集合
2.集合Collection的框架
3.Collection接口中的共性基本功能
4.迭代器
5.List接口
6.list迭代器 listIterator
7.list接口
8.Set接口
1.集合
1.集合用于存放对象,数组只能存储一种类型的数据,而集合可以存储多种类型的数据。
2.集合有多种,如ArrayList,Vector 等。
3.集合最大的父类是 Collection接口。所有不同种类的集合容器都是实现Collection接口。
4.Collection接口中定义了集合的基本功能。
2.集合Collection的框架(允许元素重复)
所有集合容器都是由Collection派生的,其中一个就是ArrayList
3.Collection接口中的共性接口功能
1.boolean add(E e) 往集合中添加一个E类型的元素 e
2.boolean addAll(Collection c) 将指定集合c中的所有元素添加
3.boolean remove(Object o) 删除集合中指定的元素o,删除后,集合的长度-1
4.boolean removeAll(Collection c ) 删除与集合c中的元素相同的元素
5.void clear() 删除所有元素
6.int size() 获取长度
7.boolean contains(Object o) 如果此Collection包含指定元素,则返回true
8.boolean containsAll(Collection c) 如果含有集合c中所有元素,则返回true
9.Object[] toArray() 返回包含此集合中所有元素的数组
10.boolean isEmpty() 判断集合是否为空
public class Main{ public static void main(String args[]) { Collection c1 = new ArrayList(); Collection c2 = new ArrayList(); //1.添加元素 c1.add("123"); c1.add("456"); c1.add("789"); c2.add("123"); c2.add("abc"); c2.add("def"); //2.删除元素 c1.remove("456"); c1.removeAll(c2); //将c1中与c2相同的元素从c1中删除 //3.清除所有元素 c1.clear(); //4.包含 System.out.println(c1.contains("789")); System.out.println(c1); }}
4.迭代器
迭代:取出元素的一个方式。通俗来说:买冰棍,还有冰棍不,有就继续给一个,还有吗,有继续给一个,还有吗?没有就算了。
迭代器:具备着迭代功能的对象。迭代器不需要 new,直接通过 iterator() 方法获取即可。
Iterator iterator() ---返回某类集合的迭代器对象
迭代器的方法:
1.boolean hasNext() 如果有下一个元素可以迭代,返回true
2. next() 返回迭代的下一个元素
3.void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素
import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;public class Main{ public static void main(String args[]) { Collection c = new ArrayList(); c.add("123"); c.add("456"); c.add("789"); Iterator it = c.iterator(); while(it.hasNext()) { System.out.println(it.next()); } }}//打印结果:123456789
5.List接口
在Collection下较为常用的有两大类: List 和 Set
List:有序的,有索引(支持随即访问),允许有重复元素
Set:不允许有重复元素
List 的特有方法:(都是围绕索引)
1.增:
add(index,element) 表示在索引index处插入element
2.删:
remove( index ) 表示删除索引 index 处的元素
3.获取:
get( index ) 表示获取索引(返回) index处的元素
indexOf( element ) 表示返回元素element的索引
4.改:
set(index,newElement) 表示把索引值为index的元素改成 newElement
5.返回List长度
size()
例子:
import java.util.*;public class Main{ public static void main(String args[]) { List list = new ArrayList();//List是个接口,所以不能实例化,ArrayList()是实现了List接口的一个类,可以实例化。 list.add("111"); list.add("222"); //在索引为1的地方插入000 list.add(1,"000"); //删除索引为1的元素 list.remove(1); //返回list长度 int len = list.size(); //遍历 list for(Iterator it = list.iterator();it.hasNext();) { System.out.println(it.next()); } }}//打印结果:111222
6.list迭代器 listIterator
当用 Collection迭代器 Iterator 来遍历 list 数据时,又想改变list,是不行的,如下:
for(Iterator it = list.iterator();it.hasNext();) { System.out.println(it.next()); Object obj = it.next(); if(obj == "222") { list.add("333"); } }会发生异常:ConcurrentModificationException
是因为迭代器和集合同时在修改容器中的元素导致了并发修改异常
若要实现边遍历容器边又可以修改容器,就只能允许迭代器来修改容器。普通的迭代器 Iterator 不具备具体的方法,但 list 的迭代器 listIterator 有。
从java 文档中可以找到,Iterator 的方法只有三个:
但listIterator 的方法却拥有包含了 list 操作的方法:
用ListIterator 边遍历容器 list 边修改 list 。如下:
for(ListIterator it = list.listIterator();it.hasNext();) //注意 ListIterator声明的时候首字母是大写,但在list 中是小写 listIterator { System.out.println(it.next()); Object obj = it.next(); if(obj == "222") { it.add("333"); } }
7.List的接口
List集合具体子类有:(子类之所以能被区分,是因为数据结构(存储数据的方法)不同)
1.vector:(不常用,因为老)可变数组,长度可变,线程同步的,速度都慢。
2.ArrayList:(替代了vector,由于ArrayList是线程不同步,所以比vector快)可变数组,长度可变,线程不同步的,增删速度不快,查询快
3.LinkedList:链表结构,线程不同步。增删速度快,查询速度慢
#属于 LinkedList 特殊的方法:
1. addFirst(E e) :将指定元素 e 放在列表的开头
2. addLast(E e):将指定元素 e 放在列表的结尾
3. getFirst() : 返回列表第一个元素
4. getLast() : 返回列表最后一个元素
5. removeFirst() :删除并返回列表第一个元素
6. removeLast() :删除并返回列表最后一个元素
#具体 ArrayList 和 LinkedList 的方法可以在 java 文档中查找。
8.Set的接口
Set集合:不允许有重复的元素,从Set取出元素的方法只有一个:迭代器
Set集合不保证存入顺序和取出顺序一致。
#HashSet判断元素该存储在哪个位置是根据元素的哈希值决定的
Set的方法:
常用的Set集合有:
1.HashSet:哈希表(散列)结构,哈希表结构查询速度比数组快
2.TreeSet:二叉树结构。存进TreeSet的元素会被强行排序,因此对于自定义元素,需要定义比较功能,目前有两种方法,一是在自定义元素中实现Comparable接口中的compareTo()方法,另一种是new TreeSet实例时,传入比较器。
(一)HashSet:
演示使用 HashSet:
import java.util.*;public class Main{ public static void main(String args[]) { Set s = new HashSet(); s.add("abc"); s.add("bcd"); s.add("efg"); for(Iterator it = s.iterator();it.hasNext();) { System.out.println(it.next()); } }}打印结果:
bcd
abc efg#用HashSet存储自定义对象
1.必须重写Object的 hashCode( ) 方法。(因为不论对象的内容是什么,只要是不同的对象,默认的hashCode方法返回的哈希值就会不同),覆盖hashCode()方法是为了根据元素自身特点决定哈希值
2.必须重写Object的equals( ) 方法,因为当哈希值冲突时,要判断元素是否为同一个元素。覆盖equals()方法是为了解决哈希冲突
import java.util.*;class Stu { public String name; public int age; Stu(String name,int age) { this.name = name; this.age = age; } public String toString() { return this.name+":"+this.age; } /*自定义的哈希方法*/ public int hashCode() { return this.age; } /*自定义的equals方法*/ public boolean equals(Object obj) { if(this == obj) return true; Stu stu = (Stu)obj; return this.name.equals(stu.name) && this.age == stu.age; }}public class Main { public static void main(String args[]) { Set set = new HashSet(); set.add(new Stu("xiaoming",25)); set.add(new Stu("xiaohong",21)); set.add(new Stu("xiaoming",25)); set.add(new Stu("zhangsan",25)); set.add(new Stu("lisi",24)); set.add(new Stu("xiaoming",25)); for(Iterator it = set.iterator();it.hasNext();) { Object obj = it.next(); Stu stu = (Stu)obj; System.out.println(stu); } }}打印结果: xiaohong:21 lisi:24 xiaoming:25 zhangsan:25
额外提一个HashSet的子类:LinkedHashSet()
HashSet是无序的,而LinkedHashSet()是有序的,即存入的顺序和取出访问时的顺序是一样的。具体用法跟HashSet()一样。
(二)TreeSet
TreeSet 有两种方法实现比较功能,一是让自定义元素类实现Comparable接口,覆盖compareTo()方法。另一种是创建TreeSet对象时传入比较器。
先看第一种方法:
可以通过下图看到compareTo()方法的返回值规则:
例子:(把Stu对象存进TreeSet,排序规则是根据age大小排序)
import java.util.*; class Stu implements Comparable{ //实现Comparable接口 public String name; public int age; Stu(String name,int age) { this.name = name; this.age = age; } public String toString() { return this.name+":"+this.age; } @Override public int compareTo(Object o) { Stu stu = (Stu)o; if(this.age > stu.age){ return 1; } if(this.age < stu.age){ return -1; } if(this.age == stu.age){ return 0; } return 0; }}public class Main { public static void main(String args[]) { Set set = new TreeSet(); set.add(new Stu("xiaoming",25)); set.add(new Stu("xiaohong",21)); set.add(new Stu("xiaoming",25)); set.add(new Stu("zhangsan",25)); set.add(new Stu("lisi",24)); set.add(new Stu("xiaoming",25)); for(Iterator it = set.iterator();it.hasNext();) { Object obj = it.next(); Stu stu = (Stu)obj; System.out.println(stu); } }}打印结果:
xiaohong:21 lisi:24 xiaoming:25
第二种方法:比较器方法 1.先定义比较器类
2.new TreeSet时传入比较器实例
import java.util.*;class Student { public String name; public int age; Student(String name,int age) { this.name = name; this.age = age; } public String toString() { return this.name+":"+this.age; } public String getname() { return this.name; } public int getage() { return this.age; }}class ComparatorByName implements Comparator{ //创建比较器类,先通过名字比较,若名字相同,再通过年龄比较 @Override public int compare(Object o1, Object o2) { Student stu1 = (Student)o1; Student stu2 = (Student)o2; int temp = stu1.getname().compareTo(stu2.getname()); return temp==0?stu1.getage() - stu2.getage():temp; }}public class Main { public static void main(String args[]) { Set set = new TreeSet(new ComparatorByName()); set.add(new Student("xiaoming",25)); set.add(new Student("xiaohong",21)); set.add(new Student("xiaoming",25)); set.add(new Student("zhangsan",25)); set.add(new Student("lisi",24)); set.add(new Student("xiaoming",25)); set.add(new Student("xiaoming",18)); for(Iterator it = set.iterator();it.hasNext();) { Object obj = it.next(); Student stu = (Student)obj; System.out.println(stu); } }}打印结果:
lisi:24 xiaohong:21 xiaoming:18 xiaoming:25 zhangsan:25