目录
| 总框架
集合的基本框架
-
首先,掌握顶层的Collection及其方法(这些方法是所有集合通用的方法)。
-
然后,学习Collection的两个子接口List和Set的特性、及其各自的实现类的使用。
Collection —— 集合之父
-
Collection的所有方法和索引无关。
public boolean add (E e); //添加元素
public void clear (); //保留集合对象,但是清空所有元素
public boolean remove (E e); //删除指定对象
public boolean contains ( E e ); //判断集合是否存在指定元素
public boolean isEmpty(); //判断集合是否为空
public int size(); //获取集合元素个数
public Object[] toArray(); //把集合转数组
Collections —— 集合工具类 & 自定义类排序
-
基本都是静态方法,直接用类名调用即可
public static void shuffle(List<?> list); //打乱集合元素(只能打乱List集合元素)
public static <E> boolean addAll (Collection<T> 集合名 , 元素1,元素2...... ); //向集合添加多个元素
public static <T> void sort ( List<T> list ); //将集合元素按照ASCII码的升序规则排序(只能排序List集合)
public static <T> void sort ( List<T> list , Comparator <? super T> ); //将集合的元素按照指定规则排序(常用于自定义类型)
下面详细介绍一下自定义类型使用Collections的sort方法的详细步骤
//方法一:原始sort方法 + “自定义类型实现Comparable接口 + 重写其compareTo方法”
//Step1.自定义类,需要手动实现Comparable<E>接口
public class Person implements Comparable<Person>{
//Step2.重写接口中的compareTo方法
@Override
public int compareTo(Person person){
//Step3.return 写上降序还是升序(this.排序参照变量 - 参数.排序参照变量 : 升序)(参数.排序参照变量 - this.排序参照变量 : 降序)
return this.getAge() - person.getAge(); //升序
}
}
//Step4.直接对Person的类使用sort即可按照age升序排序
Person p = new Person();
Collection<Person> personList = new ArrayList<>();
personList.add(new Person("Klee",8));
personList.add(new Person("Sagiri",12));
sort(p); //按照age对Person进行升序排序
//方法二:“集合名 + 重写Comparator及其compare方法(匿名内部类)” 作为sort参数
Person p = new Person();
Collection<Person> personList = new ArrayList<>();
personList.add(new Person("Klee",8));
personList.add(new Person("Sagiri",12));
//按照age对Person进行升序排序
//Step1.直接调用sort方法,传入两个参数:一个是集合对象,另一个是Comparator的匿名类
//Step4.直接对Person的类使用sort即可按照age升序排序
sort(p , new Comparator{
//Step2.重写接口中的compareTo方法
@Override
public int compareTo(Person person){
//Step3.return 写上降序还是升序(this.排序参照变量 - 参数.排序参照变量 : 升序)(参数.排序参照变量 - this.排序参照变量 : 降序)
return this.getAge() - person.getAge(); //升序
});
-
Comparator和Comparable的区别:
Comparator(是一个类):相当于找一个第三方的裁判,比较不同的值的大小
Comparable(是一个接口):自己this 和 别的参数比较,自己需要实现Comparable接口,重写比较的规则Comparator方法
Iterator —— 遍历元素
-
Iterator和索引没关系,因此迭代器是一种通用的取出集合元素的一种方式。
Iterator<E e> iterator = 集合对象名.iterator();
//迭代器循环的方式一(常用)
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//迭代器循环的方式二(了解)
for(Iterator<String> it = coll.iterator() ; it2.hasNext ; ){
String e = it.next();
System.out.println(e);
}
| List及其实现类
List的特点
-
允许存储重复的元素
-
集合是有序的 (存储元素和取出元素的顺序是一致的)
-
集合中带索引值(特有带索引的方法)
List实现类:ArrayList
-
Collection的方法,ArrayList也能用
-
下面介绍一下ArrayList的方法(这些方法 LinkedList也能用,但是效率低)
Collection<String> list = new ArrayList<>(); //若E为基本数据类型,则必须使用其包装类
System.out.println(arrayList); //ArrayList重写了toString
arrayList.add(E e); //添加元素。返回boolean
arrayList.add(int index , E e); //在索引处插入元素
arrayList.set(int index , E e); //替换索引处的元素
arrayList.get(int index); //获取索引元素。返回元素
arrayList.remove(int index); //删除索引元素。返回删除元素
arrayList.remove(E e); //删除元素
arrayList.size(); //获取长度。
List实现类:LinkedList
-
Collection的方法,LinkedList也能用
-
ArrayList的方法,LinkedList也能用(但是不推荐,效率很低)
-
下面介绍一下LinkedList特有的方法
List< E e > linkedList = new LinkedList<>( );
public void add ( E e ) ; //添加元素到列表末尾
public void addFirst ( E e ) ; //添加元素到列表开头
public void addLast ( E e ) ; //添加元素到列表末尾,此方法等效于add
public void push ( E e ) ; //将元素推入此列表所表示的堆栈 (开头) ,此方法等效于addFirst
//下列五个方法不能在空集合中使用。因而常搭配 if( ! LinkedList . isEmpty ){ } 在括号中使用
public E getFirst ( ) ; //返回列表的首元素
public E getLast ( ) ; //返回列表末尾元素
public E removeFirst ( ) ; //移除并返回此列表的首元素
public E removeLast ( ) ; //移除并返回此列表的末尾元素
public E pop ( ) ; //从此列表表示的堆栈处弹出一个元素,此方法等效于removeFirst( )
public boolean isEmpty ( ); //若列表为空 返回true
List实现类:Vector
-
已经被淘汰
-
Vector 的大小可以根据需要增大或缩小,以适应创建 Vector后进行添加或移除项的操作
-
Vector是JDK1.0最初支持的数据类型,与现在的Collection不同步(多线程)不同,Vector是同步(单线程)的,因此处理速度会很慢
-
在JDK1.2版本后,Vector也实现了Collection接口.
也就是说,在JDK1.0的时候,Vector不支持所有的Collection和List的方法!
在JDK1.2之后,Vector才支持Collection和List的方法。
| Set及其实现类
-
Set集合是集合总父类Collection的子类,是TreeSet HashSet的父类。其中HashSet 是 LinkedHashSet 的父类。
Set的特点
-
Set不允许存储重复的元素(先比较哈希值,若哈希值相同再比较内容,若内容相同则不保存到集合内)
因此,若想向Set存储自定义类型,则必须重写hashCodes和equals方法,
若不重写hashCode,则使用的是Object的方法,两个对象的Object肯定是不一样的,所以都能存进集合!!
若不重写equals,则比较的是地址,而不是内容。而不同对象的地址肯定不同,所以也都能存进集合!!
总之,重写hashCode和equals的目的是:不出现“因为对象不同,所以哈希值一定不同、地址必不同”,而存储了相同元素进HashSet集合的Bug。
-
集合是无序的 (存储元素的顺序和取出元素的顺序有可能不一致)例外如:LinkedHashSet是有序的。无序集合取出的元素可能有序
-
集合中没有索引值,因而不能使用普通的for循环遍历,只能用增强for或者迭代器遍历
Set实现类:HashSet
-
HashSet底层 在JDK1.8是 数组+链表。 JDK1.8后是 数组+链表+红黑树,当链表的长度 >8 , 则链表会转换红黑树
-
常用方法如下:
Set<String> hashSet = new HashSet<>();
hashSet.add("one"); //添加元素
hashSet.contains("one"); //判断是否存在元素
hashSet.remove("one"); //删除元素
hashSet.clear(); //清空元素
hashSet.size(); //获取元素个数
//遍历元素
for(String str : hashSet){
//...
}
Set实现类 & HashSet的子类:LinkedHashSet
-
LinkedHashSet 是有序的,底层的数组换成了链表
-
LinkedHashSet的方法和 Collection的方法、HashSet方法 一致
Set的子类:TreeSet
-
TreeSet 是一个有序集合,它的作用是提供有序的Set集合。其继承于 AbstractSet 类
-
TreeSet 实现了 NavigableSet 接口,意味着它支持一系列的导航方法。比如查找指定目标最匹配项
-
TreeSet 实现了 Serializable 接口,因此它支持序列化
-
TreeSet 是通过 TreeMap 实现的一个有序的、不可重复的集合,底层维护的是红黑树结构。当TreeSet的泛型对象不是java的基本类型的包装类时,对象需要重写 Comparable 的 compareTo()方法
-
语法
//构造方法
//默认构造方法。使用改
TreeSet()
// 创建的 TreeSet 包含 collection
TreeSet(Collection<? extends E> collection)
// 指定 TreeSet 的比较器
TreeSet(Comparator<? super E> comparator)
// 创建的 TreeSet 包含set
TreeSet(SortedSet<E> set)
| Map
-
Map是一个接口,且有两个泛型
-
Map的Key都不能重复!
-
Map和Set一样,依靠哈希值、以及内容的对比,来判断是否存在重复的Key。因此自定义类作为Map的Key,必须重写hashCode和equals方法
-
Map集合 和 Collection集合 是完全不同的一个体系!
Map的子类:HashMap
-
HashMap的集合底层是哈希表【JDK1.8后的哈希表构成为:数组+单向链表/红黑树(链表长度>8)】
HashMap不保证插入顺序,但是循环遍历时,输出顺序是不会改变的。
//创建
Map<String,String> map = new HashMap<>();
//成员方法
public V put (K key , V value); //存放KV
public V remove(Object key); //删除KV,若K存在则返回被删除的V,若K不存在则返回null
public V get(Object key); //获取K对应的V
public boolean contaimKey(Object key); //判断是否包含K
public Set<E> keySet(); //返回Map的Key组成的Set集合
map.entrySet(); //返回键值对构成的集合 Set<Map.Entry<String,String>> set
//遍历:使用迭代器
Iterator it = map.iterator();
while(it.hasNext()){
//..
}
//遍历:使用foreach
for(String key : map.keySet()){
String str = map.get(key);
}
//遍历:【特有】通过Entry遍历键值对
Set<Map.Entry<String,String>> set = map.entrySet();
for(Map.Entry<String,String> entry : map.entrySet()){
String key = entry.getKey();
String value = entry.getValue();
}
HashMap的子类:LinkedHashMap
-
LinkedHashMap的集合底层是 哈希表+链表(保证迭代的顺序)
LinkedHashMap是有序的
-
下面介绍LinkedHashMap常用方法 和HashMap方法一致
Map<String,String> mapLink = new LinkedHashMap<>();
Map的实现类:HashTable
-
已经淘汰
-
其底层是一个哈希表。该集合也是一个双列集合。