目录
集合:就是一个用来储存数据的容器
集合体系框架分为单列集合(Collection)和双列集合(Map),那么什么是单列集合?什么是双列集合?
单列集合:(Collection)代表单列集合:每个元素(数据)只包含一个值。
双列集合:(Map)代表双列集合:每个元素包含两个值(统称为:键值对)。
接下来我们对单列集合进行展开分析
Collection
List系列集合
添加的元素是有序的,可重复,无索引。
ArrayList,LinkedList:有序,可重复,无索引。
Set系列集合
添加的元素是无序,不重复,无索引。
HashSet:无序,不重复,无索引。
LinkedHashSet:有序,不重复,无索引 。(注:有序指的是插入数据的顺序)
TreeSet:按照大小默认升序排序,不重复,无索引。
Collection是单列集合的祖宗类,他规定的方法是全部单列集合都会继承的。
Collection的常用方法如下:
运行代码如下
package d1_collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionTest2 {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();//多态写法:
//添加元素,添加成功返回true
c.add("java1");
c.add("java2");
c.add("java3");
c.add("java1");
System.out.println(c);
//清空集合的元素
// c.clear();
// System.out.println(c);
//判断集合是否为空;
System.out.println(c.isEmpty());
//获取集合的大小
System.out.println(c.size());
//判断集合中是否包含某种元素
System.out.println(c.contains("java1"));//true
System.out.println(c.contains("Java1"));//false
//删除某个元素,如果有多个重复元素默认删除前面的第一个
System.out.println(c.remove("java1"));
System.out.println(c);
//把集合转换成数组
Object[] arr = c.toArray();
System.out.println(Arrays.toString(arr));
String[] arr2 = c.toArray(new String[c.size()]);
System.out.println(Arrays.toString(arr2));
System.out.println("----------");
//把一个集合中的全部数据,拷贝到另一个集合中去
Collection<String> c1 = new ArrayList<>();
c1.add("java1");
c1.add("java2");
Collection<String> c2 = new ArrayList<>();
c2.add("java3");
c2.add("java4");
c1.addAll(c2);//将c2集合的全部数据,全部拷贝到c1集合中。两者数据得是相同的
System.out.println(c1);
}
}
遍历方式:
迭代器:迭代器是用来遍历集合的专用方式(数组没有迭代器),在Java中迭代器的代表是Iterator。
Collection集合获取迭代器的方法:
Iterator迭代器中的常用方法:
使用迭代器的代码如下:
package d2_collection_traverse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo01 {
public static void main(String[] args) {
Collection<String> c =new ArrayList<>();//多态
c.add("李华");
c.add("小明");
c.add("小红");
c.add("小李");
System.out.println(c);
//遍历:
//从集合对象中获取迭代器对象:
Iterator<String> it = c.iterator();//it位置在第一个开始
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
//使用循环结合迭代器遍历集合:
while (it.hasNext()){
String ele = it.next();
System.out.println(ele);
}
}
}
增强for循环:其本质是迭代器遍历集合的简化手法,可以用来遍历集合或数组。
格式如下:
示例代码如下:
package d2_collection_traverse;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo02 {
public static void main(String[] args) {
Collection<String> c =new ArrayList<>();//多态
c.add("李华");
c.add("小明");
c.add("小红");
c.add("小李");
System.out.println(c);
//增强for循环遍历集合或者数组
for (String ele : c) {
System.out.println(ele);
}
//数组
String[] names = {"喜羊羊","美羊羊","沸羊羊"};
for(String name : names){
System.out.println(name);
}
}
}
Lambda表达式遍历循环:得益于JDK 8 开始的新技术,Lambda表达式提供一种更简单,更直接的方式来遍历集合。(认真看见话步骤,之后常用)
package d2_collection_traverse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
public class CollectionDemo03 {
public static void main(String[] args) {
Collection<String> c =new ArrayList<>();//多态
c.add("李华");
c.add("小明");
c.add("小红");
c.add("小李");
System.out.println(c);
//调用forEach方法,结合Lambda表达式遍历集合。并逐步简化
// c.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// });
//
// c.forEach((String s) -> {
// System.out.println(s);
// });
//
// c.forEach( s -> {
// System.out.println(s);
// });
//
// c.forEach( s -> System.out.println(s));
c.forEach(System.out::println);
}
}
List集合:
List集合因为支持索引,所以多了很多与索引相关的方法,当然,Collection的功能List也都继承了。
List集合的常用方法:
遍历方式:
参考Collecction,代码如下
package d3_collection_list;
import java.util.ArrayList;
import java.util.List;
public class ListTest1 {
public static void main(String[] args) {
//创建一个ArrayList集合对象(有序,可重复,有索引)
List<String> list = new ArrayList<>();
list.add("喜羊羊");
list.add("美羊羊");
list.add("沸羊羊");
System.out.println(list);
//在某个位置的索引处参入元素
list.add(3,"不是吗?");
System.out.println(list);
//根据索引删除元素,返回被删除的元素
System.out.println(list.remove(2));
System.out.println(list);
//返回集合中指定位置的元素
System.out.println(list.get(1));
//修改索引位置处的元素,修改成功后,会返回原来的数据
System.out.println(list.set(2,"牛魔王"));
System.out.println(list);
}
}
ArrayList集合:
ArrayList是基于数组实现的其特点是:
查询速度快(注:是根据索引的查询数据块):查询数据通过地址值和索引的定位,查询任意数据耗时相同
删除效率低:可能需要把后面的很多数据进行前移
添加效率极低:可能需要把后面的很多数据后移,在添加元素;或者也可能需要进行数组的扩容。
ArrayList集合的底层原理:
① 利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
② 添加第一个元素时,底层会创建一个新的长度为10的数组
③ 存满是,会扩容1.5倍
④ 如果一次添加多个元素,1.5倍还放不下,则以新创建数组的长度为准。
特点: 查询快,增删慢
应用场景:
适合:根据索引查询数据,比如根据随即索引取数据(高效)!或者数据量不是很大
不适合:数据量大的同时,又要被频繁的进行增删操作
LinkedList集合:
LinkedList集合的底层原理:
① 基于双链表实现
特点: 查询慢,增删相对较快,但对首尾元素进行增删改查士的速度是是极快的。
LinkedList新增了首尾操作的特有方法
应用场景:设计队列和栈
Set集合:
注意:Set常用到的方法,基本上就是Collection提供的!!自己几乎没有额外的新增一些常用的功能。
HashSet集合
HashSet: jdk8之前的底层原理:
基于哈希表(数组+链表+红黑树)
① 创建一个默认长度16的数组,默认加载因子为0.75,数组名table
② 使用元素的哈希值和对数组的长度求余计算出相应的存入位置
③ 判断当前位置是否为null,如果是null直接存入
④ 如果不为null,表示有元素,则调用equals方法比较,相等,则不存;不相等,则存入数组
JDK 8之前,新元素存入数组,占老元素位置,老元素挂下面
JDK 8之后,新元素直接挂在老元素下面
HashSet的去重机制:
HashSet集合默认不能对容一样的两个不同对象去重复的!比如内容一样的两个学生对象存到HashSet集合是不能去重复的。
结论:如果希望Set集合认为两个内容一样的对象是重复的,必须重写多项的hashCode()和equals()方法。
哈希值:就是一个int类型的数值,java中每个对象都有一个哈希值,且所有对象都可以调用Object类提供的hashCode方法,返回该对象自己的哈希值。
public int hashCode()://返回对象的哈希值
特点:
①、同一个对象多次调用hashCode() 方法返回的哈希值是相同的
②、不同的对象,他们的哈希值一般不相同,但也有可能会相同(哈希碰撞)
LinkedHashSet集合:
LinkedHashSet底层原理:
仍基于哈希表(数组,链表,红黑树)来实现,但是它的每个元素额外多一个双链表的机制记录它前后元素的位置
TreeSet集合:
TreeSet:
特点:
1、不重复,无索引,可排序(默认升序排序,按照元素的大小,由小到大排序)。
2、底层是基于红黑树实现的。
注意:
1、对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序。
2、对于字符串类型:默认按照首字母的编号升序排序。
3、对自定义类型如:Student对象,TreeSet默认是无法直接排序的。
自定义排序规则:
方法一、让自定义的类(如:学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则。
方法二、通过调用TreeSet集合有参构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)。
public TreeSet(Comparator<? super E> comparator)
注意:如果类本身有实现Comparable接口,TreeSet集合同时自带比较器,默认使用集合自带的比较器排序。
单列集合总结:
1、如果希望记住元素的添加顺序,需要储存重复的元素,又要频繁的根据索引查询数据?
用ArrayList集合(有序,可重复,有索引),底层是基于数组的(常用)
2、如果希望记住元素的添加顺序,且增删首位数据的情况较多?
用LinkedList集合(有序,可重复,有索引),底层是基于双链表实现的。
3、如果不在意元素顺序,也没有重复元素需要储存,只希望增删改查都快?
用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的(常用)
4、如果希望记住元素的添加顺序,也没有重复元素需要储存,只希望增删改查都快?
用LinkedHashSet集合(有序,不重复,无索引),底层是基于哈希表和双链表。
5、如果要对元素进行排序,也没有重复元素需要储存,且希望增删改查都快?
用TreeSet集合,基于红黑树实现。
集合的并发修改异常:
1、 使用迭代器遍历集合是,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。
2、由于增强for循环遍历集合就是迭代器遍历集合的简化手法,因此,增强for循环遍历集合,又在同时删除集合中的数据时,程序也会出现并发修改异常的错误。
怎么保证遍历集合同时删除数据时不出bug?
1、使用迭代器遍历集合,但用迭代器自己的删除方法删除数据即可。
2、如果能用for循环遍历时,可以到这遍历并删除;或者从前往后遍历,但删除元素后做 i--操作。
Colections常用的静态方法:
Colections只能支持对List集合进行排序
排序方式1:
注意:本方法可以直接对自定义类型List集合排序,但自定义类型必须实现Comparable接口,指定规则才能实现。
排序方式2:
双列集合在这里:http://t.csdnimg.cn/sd6w7
如有错误的地方,烦请各位佬们提出 ,如有什么版权问题,烦请联系本人改正