java集合有三大类,但在此文中值,知介绍其中的俩类,如果想了解详细的集合家族,
Java集合类主要有俩个派系Collection和Map
Collection根接口
1、概述: Collection是单列集合的根接口,定义了所有单列集合中共有的功能
2、所有的方法:
boolean add(E e)
确保此 collection 包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c)
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
void clear()
移除此 collection 中的所有元素(可选操作)。
boolean contains(Object o)
如果此 collection 包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c)
如果此 collection 包含指定 collection 中的所有元素,则返回 true。
boolean equals(Object o)
比较此 collection 与指定对象是否相等。
int hashCode()
返回此 collection 的哈希码值。
boolean isEmpty()
如果此 collection 不包含元素,则返回 true。
Iterator<E> iterator()
返回在此 collection 的元素上进行迭代的迭代器。
boolean remove(Object o)
从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
boolean removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
boolean retainAll(Collection<?> c)
仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
int size()
返回此 collection 中的元素数。
Object[] toArray()
返回包含此 collection 中所有元素的数组。
<T> T[]
toArray(T[] a)
返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
List子接口
1、概述: List 是Collection 的子接口,List接口中继承了Collection中的所有的方法,并且还增加了一些特有的方法(关于下标)
2、List集合的特点:有序、元素可以重复、有索引
3、List集合中的方法:
自己关于下标特有的方法:
add(int index,Object obj): 在指定的索引上添加指定元素
remove(int index): 根据下标删除指定的元素
set(int index,Object obj): 将指定下标的元素修改为指定的值
get(int index) 返回列表中指定位置的元素。
List遍历方式
package com.officn.day13;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
public class Demo2 {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList();
arrayList.add(1);//集合中不能添加基本数据类型,add()会自动装箱为引用数据类型
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
arrayList.add(5);
// arrayList.remove(1);//删除下标为1 的元素,remove不会自动装箱
arrayList.remove((Integer)1);//删除元素值为1的数据,
//迭代器
Iterator iterator = arrayList.iterator();
while(iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
//foreach遍历
for (Object o : arrayList) {
System.out.println(o);
}
//jdk8新特性,foreach方法 接口回调
arrayList.forEach(new Consumer<Object>() {
@Override
public void accept(Object t) {
// TODO Auto-generated method stub
System.out.println(t);
}
});
//lambda表达式
arrayList.forEach(t->System.out.println(t));
//方法引用,对lambda进一步的简化
arrayList.forEach(System.out::println);
}
}
并发修改异常
1、概念:在使用迭代器Iterator遍历结合的同时,对List进行添加/删除操作,由此产生的异常为并发修改异常
代码示例:
package com.officn.day13;
import java.util.ArrayList;
import java.util.Iterator;
public class Demo3 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("小优势");
list.add("西游记");
list.add("水浒传");
list.add("三国演义");
list.add("红楼梦");
list.add("活着");
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
Object next = iterator.next();
// //修改元素
// if(next.equals("活着")) {
// list.set(0, "小优势");
// }
//查询
if(next.equals("小优势")) {
System.out.println(list.get(list.size()-1));
}
//增加元素
// Exception in thread "main"
// java.util.ConcurrentModificationException并发修改异常
// if(next.equals("小优势")) { //迭代器执行时,不能操作list的增删
// list.add("成龙");
// }
//
// //删除元素
// Exception in thread "main"
// java.util.ConcurrentModificationException并发修改异常
// if(next.equals("小优势")) {
// list.remove("成龙");
// }
System.out.println(next);
}
}
}
并发修改异常的解决方法
1、迭代器遍历,迭代器增加
2、集合遍历,集合增加
代码示例:
package com.officn.day13;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class Demo4 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("小优势");
list.add("西游记");
list.add("水浒传");
list.add("三国演义");
list.add("红楼梦");
list.add("活着");
//集合遍历,集合添加
for(int i =0; i<list.size(); i++) {
if(list.get(i).equals("红楼梦")) {
list.add("平凡世界");
}
System.out.println(list.get(i));
}
//集合遍历,集合删除
for(int i =0; i<list.size(); i++) {
if(list.get(i).equals("红楼梦")) {
list.remove("活着");
}
System.out.println(list.get(i));
}
//迭代器遍历,迭代器删除
ListIterator iterator = list.listIterator();
while(iterator.hasNext()) {
Object next = iterator.next();
if(next.equals("活着")) {
iterator.remove();
}
System.out.println(next);
}
//迭代器遍历,迭代器添加
ListIterator<String> iterator1 = list.listIterator();
while(iterator1.hasNext()) {
Object next = iterator1.next();
if(next.equals("活着")) {
iterator1.add("悲惨世界");
}
System.out.println(next);
}
System.out.println("================");
for (Object object : list) {
System.out.println(object);
}
}
}
List集合的实现类
ArrayList
1、概念:底层采用数组形式实现,顺序存储(有List中的方法,无特有方法)
LinkedList
1、概念:底层采用节点实现,链式存储
特有方法
addFirst(Object obj):在头部添加元素
addLast(Object obj):在尾部添加元素
removeFirst():删除头部元素
removeLast():删除尾部元素
getFirst():获取头部元素
getLast():获取尾部元素
ArrayList和LinkedList比较:
List | 比较 |
---|---|
ArrayList | 查询修改快,删除增加慢,非线程安全,有索引 |
LinkList | 查询修改慢,删除增加快,非线程安全,有索引 |
验证代码
package com.officn.day13;
import java.util.ArrayList;
import java.util.LinkedList;
public class Demo5 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
LinkedList linkedList = new LinkedList();
for(int i =0; i<1000000;i++) {
arrayList.add(i);
linkedList.add(i);
}
int index = 50000;
//arrayList查询时间
long start1 = System.nanoTime();
arrayList.get(index);
long end1 = System.nanoTime();
System.out.println(end1 - start1);//5700
//linkedList查询时间
long start2 = System.nanoTime();
linkedList.get(index);
long end2 = System.nanoTime();
System.out.println(end2 - start2);//985900
//ArrayList在头添加元素
long start3 = System.nanoTime();
for (int i = 0; i < 500; i++) {
arrayList.add(0, i);
}
long end3 = System.nanoTime();//241714400
System.out.println(end3 - start3);
//LinkedList在头添加元素
long start4 = System.nanoTime();
for (int i = 0; i < 500; i++) {
linkedList.add(0, i);
}
long end4 = System.nanoTime();
System.out.println(end4 - start4);//175600
}
}
Set集合
1、概述:Set接口是Collection 根接口的子接口,和List接口是兄弟关系
2、特点:无序,不可以重复,没有索引
3、存储特点:
相同的元素无法存进set元素
集合本身不保证顺序,存进去和取出来的顺序不一定一样
HashSet:
1、概念:HashSet是Set的实现类,其底层采用的是哈希表的存储结构(数组+单向链表)
2、HashSet保证元素的唯一性原理:
重写equals方法,比较各个对象的属性值是否全部相等
重写hashCode,相同的对象要有相同的哈希值,不同的对象要有不同的哈希值
3、重写equals和hashCode方法
package com.officn.day14;
import java.util.LinkedHashSet;
public class Demo3 {
public static void main(String[] args) {
// 创建一个set集合
//HashSet<Student> students = new HashSet<Student>();
LinkedHashSet<Student> students = new LinkedHashSet<Student>();
Student s1 = new Student("小红", 16);
System.out.println(s1.hashCode());
Student s2 = new Student("小紫", 86);
System.out.println(s2.hashCode());
Student s3 = new Student("小蓝", 56);
System.out.println(s3.hashCode());
Student s4 = new Student("小黑", 166);
System.out.println(s4.hashCode());
Student s5 = new Student("小绿", 34);
System.out.println(s5.hashCode());
Student s6 = new Student("小粉", 116);
System.out.println(s6.hashCode());
//增加一个重复的元素
Student s7 = new Student("小红", 16);
System.out.println(s7.hashCode());
students.add(s1);
students.add(s2);
students.add(s2);
students.add(s2);
students.add(s3);
students.add(s4);
students.add(s5);
students.add(s6);
students.add(s7);
for (Student student : students) {
System.out.println(student);
}
}
}
class Student{
String name;
int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + 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;//如果年龄姓名相同便返回相同的hashCode
}
@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;
}
}
输出:
680868
688144
20979936
32906270
853084
39794467
680868
Student [name=刘洋, age=16]
Student [name=刘能, age=86]
Student [name=刘德化, age=56]
Student [name=范冰冰, age=166]
Student [name=李程, age=34]
Student [name=黎国祥, age=116]
LinkedHashSet
1、概念:是HashSet的一个子类,与HashSet的保证元素唯一的原理相同
2、特点:既保证元素的唯一性,又保证元素的存储顺序
Map集合
1、概述:Map: 映射 双列集合的顶级接口.
2、特点:数据存储是以(key-value)形式存储的,其中key不能重复,value可以重复
3、常用的方法
void clear()从此映射中移除所有映射关系(可选操作)。
boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。
boolean equals(Object o) 比较指定的对象与此映射是否相等。
V get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
int hashCode() 返回此映射的哈希码值。
boolean isEmpty() 如果此映射未包含键-值映射关系,则返回 true。
Set<K> keySet() 返回此映射中包含的键的 Set 视图。
V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。
V remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
int size() 返回此映射中的键-值映射关系数。
Collection<V> values() 返回此映射中包含的值的 Collection 视图。
4、Map集合的遍历:
package com.officn.day14;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.function.BiConsumer;
import java.util.Set;
public class Demo4 {
public static void main(String[] args) {
HashMap<Integer, String> hashMap = new HashMap<>();
hashMap.put(1, "多态");
hashMap.put(2, "继承");
hashMap.put(3, "封装");
hashMap.put(4, "对象");
hashMap.put(5, "异常");
hashMap.put(6, "集合");
hashMap.put(7, "泛型");
// key-Value形式遍历
Set<Integer> keySet = hashMap.keySet();
for (Integer integer : keySet) {
System.out.println(integer+"=="+hashMap.get(integer));
}
// Value遍历
Collection<String> values = hashMap.values();
for (String string : values) {
System.out.println(string);
}
// 获取所有键值对形成的一个set集合
Set<Entry<Integer, String>> entrySet = hashMap.entrySet();
for (Entry<Integer, String> entry : entrySet) {
System.out.println(entry.getKey()+"++"+entry.getValue());
}
// forEach遍历 接口回调
hashMap.forEach(new BiConsumer<Integer, String>() {
@Override
public void accept(Integer t, String u) {
System.out.println(t + "--" + u);
}
});
// Lambda表达式
hashMap.forEach((t,v)->System.out.println(t+"***"+v));
}
}
HashMap
1、概念:是Map接口的实现类,底层采用的是哈希表进行存储的.
2、HashMap保证元素的唯一性原理:
与HashSet一样为保证键的唯一性,在对象中重写equals和HashCode方法
HashSet是有HashMap实现出来的,HashSet就是HashMap的键这一列
3、一道HashMap的例题:统计一个字符串中每个字符出现的个数
package com.officn.day14;
import java.util.HashMap;
import java.util.Scanner;
public class Demo5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = "aaaabbccddd!@#@#$@#$%cc66ff";
HashMap<Character, Integer> hashMap = new HashMap<>();
for (int i = 0; i < str.length(); i++) {
char charAt = str.charAt(i);
if (hashMap.containsKey(charAt)) {
int count = hashMap.get(charAt);
hashMap.put(charAt, ++count);
}else {
hashMap.put(charAt, 1);
}
}
hashMap.forEach((t,v)->System.out.println(t+"--"+v));
}
}
LinkedHashMap
1、概念:是HashMap的子类,维护键的添加顺序
TreeMap
1、概念: 是SortedMap接口的实现类,SortedMap 是Map接口的子接口
2、特点:TreeMap可以根据键自动由小到大排序
List、Set、Map的特点表格
集合名称 | 特点 |
---|---|
List | 有序,有索引,可以重复 |
Set | 无序,没索引,不能重复 |
Map | 键是唯一的,值不是惟一的 每个键只能对应唯一的值 |