目录
一、集合体系结构
单列集合(Collection父类) | 双列集合(Map父类) |
一次添加一个 | 一次添加一对 |
List、Set等 | HashMap等 |
二、Collection单列集合
2.1 概述
Collection是所有单列集合的父类,它提供了所有单列集合可实现的接口,其下有List和Set两个接口
List集合有三个实现子类,分别是ArrayList、LinkedList和Vector(Vector现已不再维护)
Set集合下有两个实现子类,分别是HashSet和TreeSet,HashSet下又有LinkedHashSet子类
2.2 基本方法与接口
add、clear、remove、contains、isEmpty、size
注意:contains方法在底层的实现中使用的是equals方法,所以如果元素是自定义对象,需要在Java Bean中重写equals方法进行判断
2.3 遍历方式
2.3.1 迭代器遍历
通过iterator方法获取迭代器对象,hasNext判断是否存在下一个元素,next方法获取下一个元素
不依赖索引的通用型遍历方式,可以用于删除元素
package MAP;
import java.util.ArrayList;
import java.util.Iterator;
public class MyIterator {
public static void main(String[] args) {
ArrayList<String> l = new ArrayList<>();
l.add("aaa");
l.add("bbb");
l.add("ccc");
Iterator<String> E = l.iterator();
while (E.hasNext()) {
String k = E.next();
System.out.println(k);
E.remove();
}
}
}
迭代器遍历完毕时,指针不会复位;
循环中只能使用一个next方法;
迭代器遍历时,不能使用集合的方法进增加或者删除,请使用迭代器的删除方法
2.3.2 增强for遍历
只适用所有的单列集合和数组,通常用于遍历
package MAP;
import java.util.ArrayList;
public class forList {
public static void main(String[] args) {
ArrayList<String> l = new ArrayList<>();
l.add("aaa");
l.add("bbb");
l.add("ccc");
for (String str : l) {
System.out.println(str);
}
}
}
2.3.3 Lamda表达式遍历
JDK8后的新特性,使用匿名内部类的底层原理,简化为Lamda表达式的形式,通常用于遍历
ArrayList<String> l = new ArrayList<>();
l.add("aaa");
l.add("bbb");
l.add("ccc");
l.forEach(new Consumer<String>() {
@Override
public void accept(String t) {
// TODO Auto-generated method stub
System.out.println(t);
}
});
l.forEach((String s) -> {
System.out.println(s);
});
三、List集合
特点:有序(取出元素时有排列顺序)、可重复、有索引、该接口可以使用for循环操作索引
接口通用方法:add、remove、set、get
3.1 ArrayList集合
底层原理:空参创造集合,生成长度为0的数组,当添加第一个元素时,生成一个长度为10的数组。当存满时,会创建一个长度为1.5倍的新数组。若一次添加多个元素,则新数组的长度根据实际变化。
3.2 LinkedList集合
底层原理:双向链表
常用方法:addFirst、addLast、getFirst、getLast、removeFirst、removeLast
四、泛型
JDK5后推出泛型,没有泛型时,集合可以存储多种类型数据,但都以object保存,无法使用某个具体类的特殊方法
4.1 泛型擦除
Java的泛型是伪泛型。在编译阶段,泛型会检查存入的数据类型。进入集合后,所有类型会变为Object类型
也就是说,Java泛型只是实现了在编码上的泛型,在.class文件中并没有真正的控制数据类型。意思就是,数据出入集合时会变为所控制的数据类型,而在进入集合后全部都会变为Object类型
泛型不能写基本数据类型,只能写引用数据类型,泛型可以传入子类类型
4.2 泛型使用
对数据类型使用参数进行表示,提供不确定数据类型的类、方法、接口。这种做法通常见于企业级开发中
4.2.1 泛型类
package MAP;
import java.util.Arrays;
public class MyArrayList<E> {
Object[] array = new Object[10];
int size;
public boolean add(E e) {
array[size] = e;
size++;
return true;
}
@SuppressWarnings("unchecked")
public E get(int index) {
return (E) array[index];
}
@Override
public String toString() {
return Arrays.toString(array) + ", size=" + size;
}
public static void main(String[] args) {
MyArrayList<String> l = new MyArrayList<>();
l.add("aaa");
l.add("bbb");
l.add("ccc");
System.out.println(l.get(0));
System.out.println(l.toString());
}
}
4.2.2 泛型方法
package MAP;
import java.util.ArrayList;
public class ListString {
@SuppressWarnings("unchecked")
public static <E> boolean addAll(ArrayList<E> list, E... e) {
for (E element : e) {
list.add(element);
}
return true;
}
public static void main(String[] args) {
ArrayList<String> l = new ArrayList<>();
ListString.addAll(l, "aaa", "bbb", "ccc");
System.out.println(l);
}
}
4.2.3 泛型接口
package MAP;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class MyList<E> implements List<E> {
public static void main(String[] args) {
}
@Override
public int size() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'size'");
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'isEmpty'");
}
@Override
public boolean contains(Object o) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'contains'");
}
@Override
public Iterator<E> iterator() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'iterator'");
}
@Override
public Object[] toArray() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'toArray'");
}
@Override
public <T> T[] toArray(T[] a) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'toArray'");
}
@Override
public boolean add(E e) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'add'");
}
@Override
public boolean remove(Object o) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'remove'");
}
@Override
public boolean containsAll(Collection<?> c) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'containsAll'");
}
@Override
public boolean addAll(Collection<? extends E> c) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'addAll'");
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'addAll'");
}
@Override
public boolean removeAll(Collection<?> c) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'removeAll'");
}
@Override
public boolean retainAll(Collection<?> c) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'retainAll'");
}
@Override
public void clear() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'clear'");
}
@Override
public E get(int index) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'get'");
}
@Override
public E set(int index, E element) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'set'");
}
@Override
public void add(int index, E element) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'add'");
}
@Override
public E remove(int index) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'remove'");
}
@Override
public int indexOf(Object o) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'indexOf'");
}
@Override
public int lastIndexOf(Object o) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'lastIndexOf'");
}
@Override
public ListIterator<E> listIterator() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'listIterator'");
}
@Override
public ListIterator<E> listIterator(int index) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'listIterator'");
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'subList'");
}
}
4.3 泛型常见使用
4.3.1 tips
泛型中写的是什么类型,就只能传递什么类型
可以用E参数泛型来表示不确定的泛型,但是这也表示其它所有类型的泛型数据都可以被传入使用
用?通配符也可以表示不确定性类型,但可以对类型进行限定
? extends E表示可以传递E或者E的子类类型
? super E表示可以传递E或者E的父类类型
该种做法不会导致报错)
package MAP;
import java.util.ArrayList;
public class MyE {
class ye {
}
class fu extends ye {
}
class zi extends fu {
}
public static <E> void method(final ArrayList<? extends ye> e) {
}
public static void main(final String[] args) {
final ArrayList<ye> y = new ArrayList<>();
final ArrayList<fu> f = new ArrayList<>();
final ArrayList<zi> z = new ArrayList<>();
MyE.method(y);
MyE.method(f);
MyE.method(z);
}
}
五、Set集合
特点:无序(存取顺序不一致)、不重复、无索引
与List的通用方法同理,可用迭代器、增强for循环、Lamda表达式进行遍历
5.1 HashSet与LinkedSet
5.1.1 HashSet的特性与原理
无序,不重复,无索引。底层使用哈希表(JDK8中使用数组+链表+红黑树)作为数据结构。其增删改查性能都比较好
无序:其底层使用数组+链表的模式,导致一个成型的哈希表有多种存入的方式,因此取出时不一定和存入时相同
不重复:利用hashcode和equls方法对元素进行比较
无索引:因为无序,所以无法定制索引
5.1.2 哈希表理解
哈希值:对象的整数表现形式
哈希值计算:JDK中使用hashcode计算对象的hash值,且通常使用到该对象的地址
哈希值特点:在没有重写方法的情况下,默认是不同的。在重写hashcode方法的情况下,相同属性值的哈希值是一样的。在特殊情况下,也会出现哈希值相同(哈希碰撞)
5.1.3 LinkedSet
有序,不重复,无索引
有序:LinkedSet使用了双链表,记录了每个元素的前后元素,因此有序
5.2 TreeSet
5.2.1 基本原理与特性
不重复、无索引、可排序
基于红黑树的数据结构实现排序,有由小到大的顺序
5.2.2 排序规则
在整型与浮动型中按照数字由小到大排序,在字符和字符串类型中以asc码大小进行排序
当传入的元素是自定义的对象时,会报错,因为没有匹配的排序规则,因此需要重新定义排序规则,有两种方法来实现这个功能。
第一种做法是需要使用自定义类实现comparable接口,并重写其中的抽象方法,其根据compareto的返回值正负来决定新添加的值插入的位置是在红黑树的左边还是右边
第二种做法是使用比较器对象进行排序
①使用自定义类实现comparable接口
package MAP;
import java.util.TreeSet;
public class MyTreeSet implements Comparable<MyTreeSet> {
// 这是一棵名叫Hash的树
private int age;
private String name;
public MyTreeSet(int age, String name) {
this.age = age;
this.name = 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 "My name is " + this.name + " and My age is " + this.age;
}
@Override
public int compareTo(MyTreeSet o) {
return this.age - o.age;
}
public static void main(String[] args) {
MyTreeSet tree_1 = new MyTreeSet(10, "小树");
MyTreeSet tree_2 = new MyTreeSet(20, "成年树");
MyTreeSet tree_3 = new MyTreeSet(50, "老年树");
TreeSet<MyTreeSet> container = new TreeSet<MyTreeSet>();
container.add(tree_1);
container.add(tree_3);
container.add(tree_2);
for (MyTreeSet tree : container) {
System.out.println(tree);
}
}
}
②比较器对象
package MAP;
import java.util.Comparator;
import java.util.TreeSet;
public class MyTreeSet2 {
public static void main(String[] args) {
// 排序要求:字符串排序,先按长度排序,长度一样按字母排序
TreeSet<String> tree = new TreeSet<String>(new Comparator<String>() {
public int compare(String o1, String o2) {
int i = o1.length() - o2.length();
/*
* 利用三元运算符
* 当i==0时,使用第一个表达式compareTo,当i!=0时,使用第二个表达式i的实际值
*/
i = i == 0 ? o1.compareTo(o2) : i;
return i;
}
});
tree.add("aaaaaaaaa");
tree.add("aab");
tree.add("abc");
for (String te : tree) {
System.out.println(te);
}
}
}
六、Map双列集合
6.1 基本特性
元素为键值对一对数据,也称为键值对对象(Entry对象)
键不能重复,值可以重复
键值一一对应,可通过键找到值
6.2 基本方法与接口
put、remove、containsKey、containsValue、isEmpty、Size、get
put在方法在有键值对的情况下会直接覆盖原值
6.3 Map遍历方式
6.3.1 键找值
通过得到键集合的方式,使用get方法结合单列集合遍历方式来遍历Map
package MAP;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class MyMap {
public static void main(String[] args) {
// 这是一个夫妻Map
Map<String, String> couple = new HashMap<>();
couple.put("郭靖", "黄蓉");
couple.put("杨过", "小龙女");
couple.put("杨康", "穆念慈");
Set<String> keySet = new HashSet<>(couple.keySet());
for (String string : keySet) {
System.out.println(couple.get(string) + "是" + string + "的老婆");
}
}
}
6.3.2 键值对
通过EntrySet直接获取Entry对象。这里要注意Entry是Map中的接口,所以如果没有import,则需要带上引用
package MAP;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class MyMap {
public static void main(String[] args) {
// 这是一个夫妻Map
Map<String, String> couple = new HashMap<>();
couple.put("郭靖", "黄蓉");
couple.put("杨过", "小龙女");
couple.put("杨康", "穆念慈");
Set<Map.Entry<String, String>> myEntry = couple.entrySet();
for (Map.Entry<String, String> entry : myEntry) {
System.out.println(entry.getValue() + "是" + entry.getKey() + "的老婆");
}
}
}
6.3.3 Lamda表达式
package MAP;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class MyMap {
public static void main(String[] args) {
// 这是一个夫妻Map
Map<String, String> couple = new HashMap<>();
couple.put("郭靖", "黄蓉");
couple.put("杨过", "小龙女");
couple.put("杨康", "穆念慈");
couple.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
System.out.println(value + "是" + key + "的老婆");
}
});
// 简写
couple.forEach((key, value) -> System.out.println(value + "是" + key + "的老婆"));
}
}
6.4 HashMap
HashMap是Map的实现类,继承了其中的所有方法且没有新的实现方法。其底层原理是Hash表,目前是使用最多的Map集合
如果自定义对象是键,则需要重写hasCode和equals方法。自定义对象是值则不需要