1、List集合
1.1、List接口介绍
java.util.List接口继承自Collection接口,是单列集合的一个重要分支,习惯性的将实现了List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素,另外,List集合还有一个特点就是有序,即元素的存入顺序和取出顺序一致。
1.2、List接口中常用方法
List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:
- public void add(int index, E element):将指定的元素,添加到集合中指定的位置上
- public E get(int index):返回集合中指定位置上的元素
- public E remove(int index):移除列表中指定位置上的元素,返回的是被移除的元素
- public E set(int index,E element):用指定的元素替换集合中指定位置上的元素,返回值是更新前的元素。
1.3、List的实现类—ArrayList集合
java.uitl.ArrayList集合数据存储的结构是数组结构,而且是一个动态的数组,数组的容量会随着集合中元素的个数,自动的扩大或缩小。
- 添加到ArrayList集合中的元素,都会有一个整数的序号(索引、下标)从0开始
- 查找元素快,根据索引快速定位
- 增,删元素慢,因为添加一个或删除一个元素,都要把该位置以后的元素进行索引的调整。
- 日常开发中它是使用最多的一个用来查询的集合类。
package com.bdit;
import java.util.ArrayList;
import java.util.Iterator;
public class Test1 {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add(0,"wangwu");
list.add("a");
//迭代
Iterator<String> it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
list.set(0,"李四");
list.remove(0);
System.out.println("================================");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}
1.4 LinkedList集合
java.util.LinkedList集合数据存储的结构是链表结构,方便元素添加,删除的集合
LinkedList是一个双向链表结构的集合
实际开发中一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法:
package com.bdit;
import java.util.LinkedList;
public class Test2 {
public static void main(String[] args) {
LinkedList<String> list=new LinkedList<>();
list.push("a");
list.push("b");
list.push("c");
list.push("d");
list.push("e");
System.out.println("-----------"+list.pollFirst());
System.out.println("===================================");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}
2、Set接口
java.util.Set接口同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了。与List接口不同的是,Set接口中元素无序,并且都会以某种规则保证存入的元素不出现重复的。
【Set集合在数据存储和检索,效率都比较高】
2.1、HashSet集合
它所存储的元素不可重复,并且元素都是无序的即存取的顺序不一致,java.util.HashSet底层的实现类其实是一个java.util.HashMap。
package com.bdit;
import java.util.HashSet;
import java.util.Iterator;
/*
HashSet
*/
public class Test4 {
public static void main(String[] args) {
HashSet<String> hs=new HashSet<>();
hs.add("zhangsan");
hs.add("lisi");
hs.add("wangwu");
hs.add("zhangsan");
Iterator<String> it=hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println("===============================");
for(String s:hs){
System.out.println(s);
}
}
}
2.2、HashSet集合存储数据的结构(哈希表)
什么是哈希表呢?
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一个hash值得链表都存储在一个链表里,但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树结构实现,当链表长度超过阈值8时,将链表转换为红黑树,这样大大减少查找的时间。
简单的来说,哈希表是由数组+链表+红黑树实现的,如下:
往set集合储存数据时,会调用它们的hashCode方法,获得哈希码值,然后通过固定的算法获取这个元素储存的内存地址,set采用的是哈希表的方式储存数据的如果这个内存地址已经有元素,便会调用equals方法和内容进行对比,如果一直便会直接使用已存在的,如果不一致,便会进行散列存放。
package com.bdit;
import java.util.HashSet;
/*
HashSet存放自定义对象
*/
public class Test5 {
public static void main(String[] args) {
HashSet<Student> hs=new HashSet<>();
hs.add(new Student(1001,"zhangsan"));
hs.add(new Student(1001,"zhangsan"));
hs.add(new Student(1001,"zhangsan"));
hs.add(new Student(1001,"zhangsan"));
for(Student stu:hs){
System.out.println(stu);
}
}
}
package com.bdit;
import java.util.Objects;
public class Student {
private int id;
private String name;
public Student(){
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
【如果两个对象相同,则他们的hashCode值就一定相同;但是两个对象的hashCode值相同,但是这两个对象不一定相同】
2.3、LinkedHashSet
HashSet是元素无序的,如果说我们想要Set集合存储的元素时有序的呢?
在HashSet下面有一个类java.util.LinkedHashSet,它可以记录元素存储的顺序,并且能够按照所记录的顺序进行输出。
package com.bdit;
import java.util.HashSet;
import java.util.LinkedHashSet;
/*
*/
public class Test6 {
public static void main(String[] args) {
LinkedHashSet<String> set=new LinkedHashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("d");
for(String s:set){
System.out.println(s);
}
}
}
3、可变参数
在JDK5.0以后,如果我们定义一个方法需要接收多个参数,并且多个参数类型一致,我们可以对其简化成如下格式:
修饰符 返回值类型 方法名(参数类型… 参数名){
}
其实这个格式等价于:
修饰符 返回值类型 方法名(参数类型[] 数组名){
}
只是后面这种定义,在调用时必须传递数组,而前者可以直接传递数据即可。
JDK1.5后,出现的这种简化操作,…用在参数上,称为可变参数。
package com.bdit;
/*
可变参数
*/
public class Test7 {
public static void main(String[] args) {
display(7,8,9,1,7,5,6,3);
}
public static void display(int... nums){
for(int n:nums){
System.out.println(n);
}
}
}