一、集合类体系结构
【注意】:
(1)List中元素可重复,Set中元素不可重复;
(2)
表示接口,
表示对应的实现类。
二、Collection
1.创建对象
Collection<E> c = new ArrayList<>();//因为Collection是一个接口,所以采用多态的方式创建对象
【tips】:<E>里是引用类型,当元素数据类型为基本数据类型时,<E>要用对应的包装类类型。
2.常用操作
(1)增:
boolean add(E e)//将指定的元素追加到此列表的末尾
(2)删:
boolean remove(Object o)//从该集合中删除指定元素(3)置空:
void clear()//清空集合所有元素(4)查:
boolean contains(Object o)//如果此集合包含指定的元素,则返回true。(5)判空:
boolean isEmpty()//如果此集合没有任何元素,则返回true。(6)获取集合长度:
int size()//返回此列表中的元素个数。
3.遍历
(1)Iterator(迭代器):是集合专用的遍历方式,通过以下代码得到:
Iterator<E> it = 集合对象.iterator();(2)方法:
1)E next():返回迭代器中的下一个元素。
2)boolean hasNext():判断是否还有元素。
(3)遍历格式:
(3)遍历格式:
while(it.hasNext()){
E e = it.next();
System.out.println(e);
}
三、List
1.概述
List是一个有序集合(也叫序列),可以通过整数索引(从0开始)访问元素。与Set不同,List允许重复的元素。
2.特点
(1)有序:存储和取出的元素顺序一致。
(2)可重复:存储的元素可以重复。
3.常用操作
(1)增:
public boolean add(E e)//将指定的元素追加到此列表的末尾
public void add(int index,E element)//在此列表中的指定位置插入指定的元素。 将当前位于该位置的元素(如果有)和后续元素向后移动。(2)删:
4.并发修改异常(ConcurrentModificationException)
(1)异常原因:在调用.next()方法时,先调用checkForComodification()判断实际修改集合次数是否等于预期修改集合次数,如果二者不相等,就抛出并发修改异常ConcurrentModificationException。
public class ArrayList<E> implements List<E>{
protected transient int modCount = 0;//实际修改集合次数
public boolean add(E e) {
modCount++;//每调用一次add添加元素,实际修改集合次数+1
add(e, elementData, size);
return true;
}
private class Itr implements Iterator<E> {
int expectedModCount = modCount;//预期修改集合次数
public boolean hasNext() {
return cursor != size;
}
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
//如果实际修改集合次数不等于预期修改集合次数,就抛出异常
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
}
(2)处理方案:
采用for循环的形式代替while循环+Iterator进行遍历,用get()获取元素而不是.next()。
5.ListIterator(列表迭代器)
通过.listIterator()获得,是List特有的迭代器。允许沿任一方向(正向逆向)遍历列表的列表的迭代器。
(1)常用方法:
【tips】:①逆向遍历时使用while-hasPrevious()-hasNext()组合;
|
next() |
返回列表中的下一个元素 |
|
hasNext() |
判断迭代器中是否还有元素 |
|
previous() |
返回列表中的上一个元素 |
|
hasPrevious() |
判断迭代器中是否还有元素 |
| add() |
将指定的元素插入列表 |
②一般使用Iterator进行遍历操作;
③使用ListIerator中的add()可以不触发并发修改异常,因为在add()中,把modCount赋给expectedModCount了,二者必相等,再调用.next()时就不会抛出ConcurrentModificationException。
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;//保证实际修改次数等于期望修改次数
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
6.三种遍历方式
(1)while-hasNext()-next()遍历:
while(it.hasNext()){
E e = it.next();
System.out.println(e);
}
(2)for-size()-get(index)遍历:
(3)增强for循环:简化数组和Collection集合的遍历。
1)格式:
for(元素数据类型 变量名:数组名/Collecton集合){
...;
}
2)eg1:int[] arr = {1, 2, 3}; for (int i : arr) { System.out.println(i); }eg2:
String[] strArr = {"hello", "world", "java"};
for (String s : strArr) {
System.out.println(s);
}
eg3:
List<String> l = new ArrayList<>();
l.add("Hohai");
l.add("University");
for (String str : l) {
System.out.println(str);
}
四、List两个常用子类——ArrayList和LinkedList
(一)ArrayList
1.特点
底层实现是数组,查询快,增删慢。
2.常用操作
同List。
(二)LinkedList
1.特点
底层实现是链表,增删快,查询慢。
2.常用操作
(1)同List。
(2)LinkedList特有的方法:
|
public void addFirst(E e) |
在该列表开头插入指定的元素。 |
|
public void addLast(E e) |
将指定的元素追加到此列表的末尾。 |
|
public E removeFirst() |
从此列表中删除并返回第一个元素。 |
|
public E removeLast() |
从此列表中删除并返回最后一个元素。 |
|
public E getFirst() |
返回此列表中的第一个元素。 |
|
public E getLast() |
返回此列表中的最后一个元素。 |
五、Set
1.概述
Set集合是不能存储重复元素的无序集合(存储和取出的顺序不一致),不含带索引的方法,所以不能用for-size-get(index)遍历。
2.特点
(1)元素唯一性
(2)无序
(3)无索引
六、两个Set常用子类——HashSet和TreeSet
(一)HashSet
1.概述
底层实现是哈希表,是不能存储重复元素的无序集合,不含带索引的方法,所以不能用for-size-get(index)遍历。
2.哈希值
是JDK根据对象的地址/字符串/数字算出来的int类型的数值。
(1)对象哈希值的获取:Object类中的hashCode()可以返回对象的哈希值。
(2)对象哈希值的特点:
1)同一对象多次调用hashCode()返回的哈希值是一样的;
2)一般情况下,不同对象的哈希值是不同的;
3)重写hashCode()可以使不同对象的哈希值相同。
3.HashSet保证元素唯一性分析
【tips】:要保证元素唯一性,需要重写hashCode()和equals()。
4.LinkedHashSet
(1)概述:是HashSet的子类,底层由哈希表和链表实现,是不能存储重复元素的有序集合。
(2)特点:
1)元素唯一性:由哈希表实现;
2)有序:由链表实现。
(二)TreeSet
1.特点
(1)元素有序,这里的有序不是指存取顺序一致,而是指按照一定的规则排序,具体排序方法取决于使用的构造方法;
(2)元素唯一性;
(3)没有索引。
2.构造方法
(1)TreeSet():根据元素的自然序列(比如数字的自然序列就是从小到大排序)进行排序;
(2)TreeSet(Comparator comparator):根据指定的比较器(comparator)进行比较。
【tips】:“自然序列”不是指元素存储时的顺序!
3. Comparable接口的使用
(1)该接口对它的实现类对象强加一个整体排序;
(2)用TreeSet的无参构造创建的对象,存储元素时使用的是自然排序,此时需要对元素所在的类实现Comparable接口并重写compareTo(T o)方法;
(3)int compareTo(T o)方法返回值规则:当return一个正整数时,表示对象o比调用compareTo方法的对象大;当return一个负整数时,表示o比调用对象小;当return返回0时,表示二者相等;
(3)int compareTo(T o)方法返回值规则:当return一个正整数时,表示对象o比调用compareTo方法的对象大;当return一个负整数时,表示o比调用对象小;当return返回0时,表示二者相等;
(4)重写compareTo方法时要注意排序规则的主、次要条件。
4. 比较器排序Comparator的使用
(1)用TreeSet存储自定义对象时,带参构造方法使用的是比较器排序对元素进行排序;
(2)比较器排序就是让TreeSet集合的带参构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法;
(3)重写compare方法时要注意排序规则的主、次要条件。
【tips】:①类名或接口名作形参时,实际需要接收的是继承该类的子类对象或实现该接口的实现类对象,而匿名内部类的本质就是一个对象,因此可以直接在()里new一个匿名内部类;
②o1是新添加的元素。
七、泛型
1.概述
泛型提供了在编译时类型安全监测机制,允许在编译时监测到非法的类型。泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数,把原来具体的类型参数化,在使用或调用时再传入具体的类型。
2.优点
(1)避免了强制类型转换:不使用泛型时数据类型默认是Object类型,想使用具体的数据类型时就要进行强制类型转换,而泛型的使用就避免了这种强制类型转换;
(2)把运行时才会发现的问题(ClassCastException)提前到了在编译期间就可以被发现:当使用了泛型后,在编译再添加泛型外的类型时,会直接报错。
3.分类
泛型类、泛型方法、泛型接口
(1)泛型类:
1)定义格式:
修饰符 class 类名 <类型>{}
2)eg:
public class Generic<T>{
private T t;
public T getT(){
return t;
}
public void setT(T t){
this.t = t;
}
}
“把原来具体的类型参数化,在使用或调用时再传入具体类型”:在创建Generic类的对象时,<>里可以填任意想用的数据类型。
GenericClass<String> gc = new GenericClass<>();
gc.setT("hello");
System.out.println(gc.getT());//"hello"
GenericClass<Integer> gc2 = new GenericClass<>();
gc2.setT(100);
System.out.println(gc2.getT());//100
GenericClass<Boolean> gc3 = new GenericClass<>();
gc3.setT(true);
System.out.println(gc3.getT());//true
(2)泛型方法:
定义格式:修饰符 <类型> 返回值类型 方法名(类型 类型名)
(3)泛型接口:
定义格式:修饰符 interface 接口名 <类型> {}
【注意】:泛型接口的实现类也要写成泛型类的形式。
4.类型通配符<?>
(1)List<?>:表示元素可以是任意类型的List;
List<?> l1=new ArrayList<Object>(); List<?> l2=new ArrayList<Number>(); List<?> l3=new ArrayList<Integer>();
【注意】:这种带通配符的List仅仅代表它是各种泛型List的父类,并不能把元素添加到其中。
(2)类型通配符上限:List<? extends Number>只能表示Number或Number的子类;
//List<? extends Number> l4=new ArrayList<Object>();//报错,Object超出了类型通配符上限 List<? extends Number> l5=new ArrayList<Number>(); List<? extends Number> l6=new ArrayList<Integer>();
(3)类型通配符下限:List<? super Number>只能表示Number或Number的父类。
List<? super Number> l7=new ArrayList<Object>(); List<? super Number> l8=new ArrayList<Number>(); //List<? super Number> l9=new ArrayList<Integer>();//报错,Integer超出了类型通配符的下限
【tips】:Integer extends Number extends Object
5.可变参数
(1)可变参数:作为方法的形参,形参个数可变。
(2)定义格式:修饰符 返回值类型 方法名(数据类型... 变量名){}
【tips】:①这些可变的参数被封装在一个数组里了,所以这里的变量名其实是一个数组名;
②当包含可变参数的多个参数作形参时,可变参数要放在最后。
public int sum(int b,int... a) //public int sum(int... a,int b)//报错(3)可变参数的使用:
1)Arrays工具类中有一个静态方法:
public static <T> List<T> asList(T... a)//返回由指定数组支持的固定大小的List列表。【注意】:通过asList返回的List集合不能进行增删操作,可以进行修改(set)操作。
2)List接口中有一个静态方法:
static <E> List<E> of(E... elements)//返回包含任意数量元素的不可变List列表。【注意】:通过of返回的List集合不能进行增删改操作。
3)Set接口中有一个静态方法:
static <E> Set<E> of(E... elements)//返回包含任意数量元素的不可变Set集合。【注意】:通过of返回的Set集合不能进行增删操作。(Set没有索引,本来就不能调用set()方法)
八、Map
1.概述
interface Map<K,V> K:键的类型,V:键映射的值的类型
【注意】:①键是唯一的;②键与值一一对应;③使用多态的方式创建Map对象
2.常用操作
|
V put(K key,V value) |
添加键值对元素 |
|
V remove(Object key) |
根据指定键删除该键值对元素,并返回该键映射的值 |
|
boolean containsKey(Object key) |
判断集合中是否有指定键 |
|
boolean containsValue(Object value) |
判断集合中是否有指定值 |
|
void clear() |
删除所有的键值对元素 |
|
boolean isEmpty() |
判断集合是否为空 |
|
int size() |
返回集合中的键值对的对数(即集合长度) |
3.获取操作
|
V get(Object key) |
根据键,返回值;没有该键的映射就返回null |
|
Set<K> keySet() |
返回包含所有键的Set集合 |
|
Collection<V> values() |
返回包含所有值的Collection集合 |
|
Set<Map.Entry<K,V>> entrySet() |
返回包含所有整个键值对对象的Set集合 |
4.遍历
(1)keySet-增强for-get遍历:
思路:先获取所有键,再获取每个键,最后根据每个键获取值。
//获取所有键
Set<String> keySet = m.keySet();
//获取每一个键
for (String key : keySet) {
//根据键找值
String value = m.get(key);
//输出键值对
System.out.println(key + "--" + value);
(2)entrySet-增强for-getKey/Value遍历
思路:先获取所有的键值对,再获取每一对键值对,最后分别获取键和值并输出。
//获取所有的键值对
Set<Map.Entry<String, String>> kv = m.entrySet();
//获取每一对键值对
for (Map.Entry<String, String> me : kv) {
//分别获取键和值并输出
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "-" + value);
}
【tips】:这两种遍历方式中,获取每个键和获取每对键值对用的都是增强for。5.Properties
(1)概述:Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
public class Properties extends Hashtable<Object,Object>:Properties继承了Hashtable ,是Map体系下的集合,但不建议使用Map集合的方法,因为Properties有自己特有的方法。
【注意】:Properties虽然继承了Hashtable<Object,Object>,但它没有使用泛型,因为属性列表中的每个键及其对应的值都是字符串类型。
(2)特有方法:
|
Object setProperty(String key, String value) |
向Properties对象中添加一个都是String类型的键值对。(代替put方法) |
| String getProperty(String key) | 获取指定键对应的值。 |
| Set<String> stringPropertyNames() | 获取一个存有所有键的Set集合。 |
|
void load(InputStream inStream) |
从字节输入流读取键值对,可用来通过字节输入流把文件中的键值对存入Properties集合。 |
|
void load(Reader reader) |
从字符输入流读取键值对,可用来通过字符输入流把文件中的键值对存入Properties集合。 |
|
void store(OutputStream out, String comments) |
将键值对写入字节输出流,可用来将Properties集合中的键值对通过字节输出流写入文件。 |
|
void store(Writer writer, String comments) |
将键值对写入字符输出流,可用来将Properties集合中的键值对通过字符输出流写入文件。 |
九、Collections工具类
1.概述
Collections是针对集合操作的工具类。
2.常用方法
|
public static <T> void sort(List<T> list,Comparator<? super T> c) |
根据其元素的自然排序,将指定的列表按升序排序。 |
|
public static void reverse(List<?> list) |
反转list列表中元素的顺序。 |
|
public static void shuffle(List<?> list) |
使用默认的随机源随机排列指定的列表。 |

京公网安备 11010502036488号