1 集合的概念
Java集合类存放在Java.util包中,用来存放对象的容器。需要注意:集合只能存放对象;存放的是对象的引用,对象本身还是存放在堆内存中;可以存放多种数据类型。
2 集合的框架
3 详解
1)Iterable:迭代器,它是Java集合的顶级接口。(不包含map类型的集合,Map接口是Map类集合的顶级接口)
核心方法:
Object next():返回迭代器刚越过元素的引用;
boolean hasNext():判断容器中是否有可供访问的元素;
void remove():删除迭代器刚越过的元素。
Iterable接口封装了Iterator接口。
public interface Iterable<T> {
Iterator<T> iterator();
}
只要实现了Iterable接口的类,都可以使用Iterator迭代器。Iterator主要有next(),hasNext();remove()三个方法。
如下是一个迭代器的实例
//创建一个 List 集合
List list = new ArrayList();
//添加三个元素
list.add(1);
list.add(2);
list.add(3);
//构造 List 的迭代器
Iterator it = list.iterator();
//通过迭代器遍历元素
while(it.hasNext()){
Object obj = it.next();
System.out.println(obj);
}
for each循环其实内部也是依赖与Iterator迭代器.
for( Integer i:list){
System.out.println(i);
}
反编译
Integer i;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
i = (Integer)iterator.next();
}
2)Collection :存储无序的,不唯一的数据,是list和set接口的父接口。
public interface Collection<E> extends Iteration<E>{}
主要方法有:
boolean add(Object obj) 添加对象到集合
boolean addAll(Collection c)将集合C中所有元素添加到该集合
boolean remove(Object o)删除指定的对象
boolean removeAll(Collection c)从集合中删除集合C中包含的元素
boolean retainAll(Collection c)从集合中删除集合C中不包含的元素
void clear() 删除集合中的所有元素
int size() 返回集合中元素的个数
boolean isEmpty()判断集合是否为空
boolean contains(Object obj) 判断集合中是否有指定的元素
boolean containsAll(Collection c)判断集合中是否包含集合C中的元素
Iterator iterator()返回一个迭代器
3)List:有序的,可以重复的集合。List接口继承Collection。位置从0开始
public interface List<E> extends Collection<E>{}
因为List继承了Collection,所以List拥有Collection的方法,但它也有特定的方法。
List的主要方法:
void add(int index,Object obj)在指定位置上添加一个元素
boolean addAll(int index,Collection c)将集合C的元素添加到指定位置
Object remove(int index)删除指定的元素,返回被删除的元素
Object get(int index) 返回集合List中指定的元素
int indexOf(Object obj)返回第一个出现obj元素的位置,没有返回-1
Object set(int index,Object obj) 用元素obj取代位置index上的元素,返回被取代的元素
List 接口的实现:
①List list1 = new ArrayList();底层数据结构是数组,查询快,增删慢;线程不安全,效率高
②List list2 = new Vector(); 底层数据结构是数组,查询快,增删慢;线程安全,效率低,几乎已经淘汰了这个集合
③List list3 = new LinkedList(); 底层数据结构是链表,查询慢,增删快;线程不安全,效率高
4)Set:无序的,不重复的集合。继承了Collection。
Set接口的主要实现类
1.Set hashSet = new HashSet();
HashSet按元素的哈希值存储,是无序的,不可重复的,是非线程安全的,集合元素可以为null,但最多允许一个null元素。底层是一个数组,对于hashSet,两个对象通过equals()方法返回true,这两个对象的hashCode值也应该相同。
当向HashSet集合中存入一个元素时,HashSet会先调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置。
如果 hashCode 值不同,直接把该元素存储到 hashCode() 指定的位置;如果 hashCode 值相同,那么会继续判断该元素和集合对象的 equals() 作比较:
1.hashCode 相同,equals 为 true,则视为同一个对象,不保存在 hashSet()中。
2.hashCode 相同,equals 为 false,则存储在之前对象同槽位的链表上。
2.Set treeSet = new TreeSet();
TreeSet是有序的,不可重复的,底层使用红黑树算法,默认是自然排序。
红黑树:是一种特定类型的二叉树,左小右大。
排序
①自然排序。添加元素必须实现comparable接口,重写compareto(Object obj)方法。
package com.aem.sheep.test;
import java.util.Set;
import java.util.TreeSet;
public class test {
public static void main(String[] args) throws Exception {
Set t = new TreeSet();
t.add(new Student(25, "aa"));
t.add(new Student(22, "bb"));
t.add(new Student(23, "cc"));
t.add(new Student(22, "dd"));
t.add(new Student(20, "ee"));
t.add(new Student(20, "ee"));
System.out.println(t);
System.out.println(t.size());
}
}
class Student implements Comparable {
public Student(int age, String name) {
this.age = age;
this.name = name;
}
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [ age=" + age + ", name=" + name + "]";
}
public int hashCode() {
return name.hashCode() + age * 37;
}
public boolean equals(Object obj) {
if (!(obj instanceof Student)) {
return false;
}
Student st = (Student) obj;
return this.name.equals(st.name) && this.age == st.age;
}
@Override
public int compareTo(Object obj) {
// TODO Auto-generated method stub
Student s = (Student) obj;
if (this.age > s.age) {
return 1;
}
if (this.age < s.age) {
return -1;
}
return this.name.compareTo(s.name);
}
}
②自定义排序。定义一个类实现comparator接口,重写compare()方法,并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。
当Comparable,Comparator都同时存在,以Comparator比较方式为主。
package com.aem.sheep.test;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class test {
public static void main(String[] args) throws Exception {
Set ts = new TreeSet(new MyComparator());
ts.add(new Student("aa", 20));
ts.add(new Student("bb", 25));
ts.add(new Student("cc", 30));
ts.add(new Student("dd", 23));
ts.add(new Student("ab", 20));
ts.add(new Student("bc", 20));
System.out.println(ts);
System.out.println(ts.size());
}
}
class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
Student b1 = (Student) obj1;
Student b2 = (Student) obj2;
if (b1.getage() > b2.getage()) {
return 1;
}
if (b1.getage() < b2.getage()) {
return -1;
}
return b1.getName().compareTo(b2.getName());
}
}
class Student {
private String name;
private int age;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getage() {
return age;
}
public void setage(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
3. Set linkedHashSet = new LinkedHashSet();
LinkedHashSet是有序的,不可重复的,底层采用链表和哈希表算法,链表保证了元素的添加顺序,哈希表保证了元素的唯一性。
5)queue:队列,遵循“先进先出”原则。LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。
核心方法:
add() 增加一个元索 如果队列已满,则抛IIIegaISlabEepeplian异常
remove() 移除并返回队列头部的元素 如果队列为空,则抛出一个 NoSuchElementException异常
element() 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer() 添加一个元素并返回true 如果队列已满,则返回false
poll() 移除并返问队列头部的元素 如果队列为空,则返回null
peek() 返回队列头部的元素 如果队列为空,则返回null
put() 添加一个元素 如果队列满,则阻塞
take() 移除并返回队列头部的元素 如果队列为空,则阻塞
推荐使用 offer(),poll(),peek()方法。
package com.aem.sheep.test;
import java.util.LinkedList;
import java.util.Queue;
public class test {
public static void main(String[] args) throws Exception {
Queue q = new LinkedList();
q.offer("aa");
q.offer(11);
q.offer("bb");
q.offer(22);
q.offer("cc");
q.offer(33);
System.out.println(q);
System.out.println("删除的元素:" + q.poll());
System.out.println(q);
System.out.println(q.peek());
System.out.println(q);
}
}
6)Map:key-value形式的键值队,key不允许重复,value可以重复。
主要的方法:
Object put(Object key,Object value);添加元素,指点相关联的key,value值。
void putAll(Map map);将指定map 中的所有映射复制到此集合中。
int size ();返回键值映射的数量。
boolean isEmpty();不包含键值映射返回true。
void clear();删除map中的所有键值映射。
Object remove(Object key);删除map中指定的指定的key和相关的值。
Object get(Object key);返回指定key关联的值。
Set<Entry<Object, Object>> entrySet(); 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素。
Set keySet();返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)。
boolean containsKey(Object key); 如果 Map 包含指定键的映射,则返回 true。
boolean containsValue(Object value);如果此 Map 将一个或多个键映射到指定值,则返回 true。
package com.aem.sheep.test;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class test {
public static void main(String[] args) throws Exception {
Map<String, Integer> map1 = new HashMap<String, Integer>();
Map<String, Integer> map2 = new HashMap<String, Integer>();
map1.put("A1", 1);
map1.put("A2", 2);
map2.put("B1", 11);
map2.putAll(map1);
// entrySet() 迭代器速度最快
Set<Entry<String, Integer>> set = map2.entrySet();
Iterator<Entry<String, Integer>> it = set.iterator();
while (it.hasNext()) {
Map.Entry<String, Integer> m = it.next();
System.out.println(m.getKey() + ":" + m.getValue());
}
// 合并
Iterator<Map.Entry<String, Integer>> it1 = map2.entrySet().iterator();
while (it1.hasNext()) {
Map.Entry<String, Integer> m1 = it1.next();
System.out.println(m1.getKey() + ":" + m1.getValue());
}
// keySet();
Set<String> set2 = map2.keySet();
Iterator<String> it2 = set2.iterator();
while (it2.hasNext()) {
String key = it2.next();
Integer value = map2.get(key);
System.out.println(key + ":" + value);
}
// 合并
Iterator<String> it3 = map2.keySet().iterator();
while (it3.hasNext()) {
String key = it3.next();
Integer value = map2.get(key);
System.out.println(key + ":" + value);
}
}
}
实现方式
1.Map hashmap = new HashMap();
HashMap最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null。非同步的。
实现原理:
当往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
2. Map treeMap = new TreeMap();
TreeMap能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
3.Map hashMap = new Hashtable();
Hashtable与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
4.Map linkedHashMap = new LinkedHashMap();
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。