1.LinkedList
1.1链式结构
LinkedList也是一个集合,是一个链式结构的集合,删除和增加的效率高,
- 因为提供了大量的首尾操作
- 常用的方法:
- void addFirst(E e)—-添加首个元素
- void addLast(E e)—-添加最后元素
- E getFirst()————获取首个元素
- E getLast()————-获取最后元素 ```java package com.igeek_01;
/**
- @author Lynn
- @create 2020-12-08-10:04 */
import javax.sound.midi.Soundbank; import java.util.Iterator; import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
//创建集合对象
LinkedList
//获取元素
String name= list.get(1);
System.out.println(name);
//返回迭代器
Iterator<String> iterator= list.iterator();
//问取删
while (iterator.hasNext()){
String thisName= iterator.next();
System.out.println(thisName);
}
System.out.println("---------------------------------");
//首尾操作
System.out.println(list);
list.addFirst("王嘉尔");
list.addLast("王一博");
System.out.println(list);
System.out.println(list.getFirst());
System.out.println(list.getLast());
//删除
list.remove(3);
System.out.println(list);
}
}
<a name="oxqNN"></a>
# 2.数据结构
<a name="FjPYz"></a>
### 2.1Stack-----栈
Stack结构的演示
- **栈结构---遵循先进后出的原则**
- <br />
- 对应的方法:
- 1.push:压栈---先进后出
- 2.pop:弹栈--将元素直接弹出--意味着这个元素在栈中没有了
- 3.peek:查询出即将弹出的是哪个元素-检查有没有需要弹出的元素--只看不弹出--
- 意味着元素还在栈中
- <br />
- LinkedList是支持栈结构的
- java中专门提供了一个结构--Stack
```java
package com.igeek_02;
/**
* @author Lynn
* @create 2020-12-08-10:20
*/
import com.sun.prism.shader.Solid_TextureYV12_AlphaTest_Loader;
import java.util.LinkedList;
public class StackDemo {
public static void main(String[] args) {
//创建栈结构
LinkedList<String> stack=new LinkedList<>();
//添加元素
/* stack.add("王嘉尔");
stack.add("王一博");
stack.add("白敬亭");
stack.add("刘诗诗");
stack.add("赵丽颖");
stack.add("谭松韵");*/
//因为支持栈结构,所以有push方法
stack.push("王嘉尔");
stack.push("王一博");
stack.push("白敬亭");
stack.push("刘诗诗");
stack.push("赵丽颖");
stack.push("谭松韵");
//查询结果
System.out.println(stack);
System.out.println("--------------------------");
//获取一个元素,此时由于是栈结构,所以获取的是最后压栈的元素
String name=stack.pop();
System.out.println(name);
System.out.println(stack);
System.out.println("--------------------------");
//peek
String peekname=stack.peek();
System.out.println(peekname);
System.out.println(stack);
}
}
2.2Queue—队列
队列结构演示:
- 队列结构支持:先进先出的原则
- LinkedList支持队列结构!!
- 因为这个LinkedList本身是链式结构,所以添加和删除比较灵活,而栈和队列都是
- 数据结构中的操作,所以利用LinkedList支持比较方便
- 对应的方法:
- offer:加入队列
- poll:(获取的是最早进入的元素)离开队列—该元素已经不在队列中了
- peek:查询出即将离开队列的是哪个元素—只看不离开—该元素还在队列中 ```java package com.igeek_02;
/**
- @author Lynn
- @create 2020-12-08-10:36 */
import java.util.LinkedList;
public class QueueDemo {
public static void main(String[] args) {
//利用LinkedList支持队列
LinkedList
System.out.println("----------------------------");
//获取一个元素,此时由于是队列结构,所以获取的是最早进入的元素
System.out.println(queue.poll());
System.out.println(queue);
System.out.println("----------------------------");
//peek
System.out.println(queue.peek());
System.out.println(queue);
}
}
<a name="5d62p"></a>
# 数组结构和链表结构
<a name="aQUKT"></a>
## 1.1 ArrayList数组实现的原理
数组实现的特点:查询快,增删慢<br />原因:<br /> 查询快:由于数组的索引支持,那么可以通过索引直接计算出元素的地址值,因此就可以直接通过元素的地址值获取到指定的元素<br />增删慢:由于在添加元素的时候,实际上底层会先创建一个新数组(新数组的长度为原数组的长度+1),那么在添加新元素的时候,先需要对数组中原有的数据进行拷贝,其次在末尾进行添加新的元素<br />因此,这样操作的效率的极低的(删除元素 刚好和添加的操作相反)
<a name="2L8B2"></a>
## 1.2 LinkedList链表实现的原理
链表结构:查询慢,增删快<br />查询慢:由于不能直接找到元素的地址,需要上一个元素推导出下一个元素的地址,<br />这种查询速度较慢<br />增删快:在添加的时候,只需要更改元素所记录的地址值即可
<a name="VEAlV"></a>
# 3.HashSet集合
HashSet也是一个集合,**不包含重复的元素和相同的元素,无序的,不提供索引(下标**),
- 所以不能通过下标获取元素,只能通过**迭代器访问---增强for循环**
- <br />
- HashSet怎么做到不重复的?
- 1.首先在元素存放进这个集合之前会通过HashCode()方法算出哈希值(int类型)
- 2.比较当前这个哈希值在集合中是否已经存在,如果存在就不保存
- <br />
- 所以HashSet称之为**无序不可重复**集
```java
package com.igeek_03;
/**
* @author Lynn
* @create 2020-12-08-11:05
*/
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet也是一个集合,不包含重复的元素和相同的元素,无序的,不提供索引(下标),
* 所以不能通过下标获取元素,只能通过迭代器访问---增强for循环
*
* HashSet怎么做到不重复的?
* 1.首先在元素存放进这个集合之前会通过HashCode()方法算出哈希值(int类型)
* 2.比较当前这个哈希值在集合中是否已经存在,如果存在就不保存
*
* 所以HashSet称之为无序不可重复集
*/
public class HashSetDemo {
public static void main(String[] args) {
//创建集合对象
HashSet<String> set=new HashSet<>();
//向集合中添加元素--无序,不可重复
set.add("王嘉尔");
set.add("王嘉尔");
set.add("王一博");
set.add("赵丽颖");
set.add("白敬亭");
set.add("白敬亭");
set.add("谭松韵");
set.add("刘诗诗");
//打印结果
System.out.println(set);
//获取元素--只能使用迭代器
Iterator<String> iterator= set.iterator();
while (iterator.hasNext()){
//推荐向下转型--强类型转换---目的是为了增加代码的健壮性---
//转成最后需要接受的类型
String thisName = (String)iterator.next();
System.out.println(thisName);
}
System.out.println("----------------------");
//增强for循环底层就是一个迭代器
for (String name:set){
System.out.println(name);
}
//普通for循环
for (int i = 0; i < set.size() ; i++) {
//HashSet没有下标,所以不提供get方法,get方法根据下标获取对应元素
// System.out.println(set.get(i));
}
}
}
练习
package com.igeek_03;
import java.util.HashSet;
import java.util.Iterator;
/**
* @author Lynn
* @create 2020-12-08-11:25
*/
/**
* fdasffkdsajfasFJKFDSAJKdfefoeaf
* <p>
* 分析:
* 1.将字符串拆分为一个个单个的字符
* 2.判断字符是否为字母
* 如果是字母,放到一个set集合中
* 3.查看set集合的长度
*/
public class HashSetTest {
public static void main(String[] args) {
//准备一个字符串
String s = "fdasffkdsajfasFJKFDSAJKdfefoeaf";
//定义一个不含重复元素的集合
HashSet<Character> set = new HashSet<>();
//拆分字符串
char[] chars = s.toCharArray();
//遍历---无下标的
for (char c : chars) {
//判断字符是否为字母,如果是字母,放到一个set集合中
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){
set.add(c);
}
}
//查看
System.out.println(set);
System.out.println(set.size());
}
}
4.ArrayList中有一个方法:Contains用来判断是否有重复的元素
boolean Contains(Objects o)—判断集合中是否有指定的元素
- 为了实现这个功能,我们需要新建一个实体类,是Object的子类,具备了equals方法
- Contains方法会调用参数的equals方法,依次为集合中的已经存在的对象进行比较
- 例如:新建一个Person子类继承Object。直接调用equals方法 ```java package com.igeek_04;
/**
- @author Lynn
- @create 2020-12-08-14:23 */
/**
实体类 */ public class Person { private String name; private int age;
public Person() { }
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写equals方法
/**
- 目的是比较两个对象像不像
- @param obj
@return */ @Override public boolean equals(Object obj){ System.out.println(“equals方法被调用了”);
//this:表示contains方法的参数对象 //obj:集合中原有的对象 //将Object类型的obj强制转换为子类类型(向下转型) Person otherP=(Person)obj;
//重写比较规则 //比较的是当前的对象的属性:姓名,年龄 if (!this.getName().equals(otherP.getName())){
return false;
} if (this.getAge()!= otherP.getAge()){
return false;
} //如果上面两个都不是false,则返回true return true; } }
/**
- @author Lynn
- @create 2020-12-08-14:19 */
import java.util.ArrayList;
public class ArrayListContainsDemo {
public static void main(String[] args) {
//创建集合
ArrayList
//判断--Contains方法中大小写敏感
System.out.println(list.contains("jack"));//false
System.out.println("==================================");
//对象比较
ArrayList<Person> list2=new ArrayList<>();
list2.add(new Person("宋远桥",45));
list2.add(new Person("俞莲舟",40));
list2.add(new Person("张翠山",32));
Person p=new Person("殷素素",30);
list2.add(p);
//equals方法默认的比较对象的方式是比较地址值,即==
System.out.println(list2.contains(new Person("宋远桥",45)));
//false--比较的是地址值
// System.out.println(list2.contains(p));//true
}
}
<a name="45QV3"></a>
# 5.HashSet判断元素唯一性
HashSet这个集合中添加元素的方法在执行添加的时候,会判断元素是否已经存在:
- HashSet判断元素唯一性的规则:
- 1.把对象加入到HashSet的时候,会先使用对象的HashCode方法,来生成一个哈希值,
- 判断对象加入的位置
- 2.如果比较的位置,没有其他对象存在,则判断元素不同,可以加入新的对象
- 3.如果比较的位置,有其他对象存在,接着比较HashCode值和equals比较结果
- 返回true则相同,不能存入新的对象,如果是false则不同,添加新的对象
- <br />
- 需求:
- 要求比较两个对象的属性和内容是否相同,而非比较对象的地址值
- 此时我们可以重写Person类中的HashCode方法和equals方法,将Object类中的方法重写
<a name="L0qWW"></a>
### 重写equals方法
```java
/*
* 如果没有重写该equals方法,则比较地址值.
* 我们希望比较两个对象时,比较属性内容,所以重写该方法.
*/
/**
* @Title: equals
* @Description: Person对象比较是否相等的方法
* @param obj
* @return
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
System.out.println("equals方法被调用了");
//this:contains方法的参数对象
//obj:集合当中原有元素
//将Object类型的obj强转为子类类型
Person otherP = (Person)obj;
//比较姓名
if(!this.name.equals(otherP.name)) {
return false;
}
//比较年龄
if(this.age != otherP.age){
return false;
}
//如果所有属性值均相同,就返回true
return true;
}
重写HashCode方法
//没有重写hashCode方法时,hashCode方法继承父类方法,返回的是地址值
//重写hashCode方法,通过属性值返回一个整数数字
//即对象的hashCode值,就是各个属性的hashCode值之和
//引用数据类型属性,调用hashCode方法回去
//基本数值类型属性,直接就是数值本身
/**
* @Title: hashCode
* @Description: Person对象的hashCode值算法方法
* @return
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
//张三 18 >> 56*系数 + 18 = 74
//李四 56 >> 18*系数 + 56 = 74
//理想上,不同属性值应该返回不同的hashCode值,可以在每次结果后乘以一个固定系数,避免该情况发生
//定义变量,记录要返回的hashCode值
int thisHashCode = 0;
//获取name属性的hashCode值
thisHashCode += name.hashCode()*17;
//获取age数只给你的hashCode值
thisHashCode += age;
return thisHashCode;
}
package com.igeek_05;
/**
* @author Lynn
* @create 2020-12-08-14:23
*/
/**
* 实体类
*/
public class Person1 {
private String name;
private int age;
public Person1() {
}
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写equals方法
/**
* 目的是比较两个对象像不像
* @param obj
* @return
*/
@Override
public boolean equals(Object obj){
System.out.println("equals方法被调用了");
//this:表示contains方法的参数对象
//obj:集合中原有的对象
//将Object类型的obj强制转换为子类类型(向下转型)
Person1 otherP=(Person1)obj;
//重写比较规则
//比较的是当前的对象的属性:姓名,年龄
if (!this.getName().equals(otherP.getName())){
return false;
}
if (this.getAge()!= otherP.getAge()){
return false;
}
//如果上面两个都不是false,则返回true
return true;
}
//重写HashCode方法
public int hashCode(){
System.out.println("hashCode方法被调用了");
//定义一个变量
int thisHashCode=0;
//张三,18 56*系数+18=74
//李四,56 18*系数+56=74
//获取name属性的HashCode值
thisHashCode+=this.name.hashCode()*17;
//获取age属性的HashCode值,就是age本身
thisHashCode+=this.age;
return thisHashCode;
}
}
package com.igeek_05;
/**
* @author Lynn
* @create 2020-12-08-15:07
*/
import java.util.HashSet;
public class HashSetAddDemo1 {
public static void main(String[] args) {
HashSet<Person1> set=new HashSet<>();
Person1 p=new Person1("张三丰",120);
Person1 p2=new Person1("郭襄",100);
Person1 p3=new Person1("杨过",110);
//添加到集合中
set.add(p);
set.add(p2);
set.add(p3);
// System.out.println(set);
//调用equals方法
//再次调用add方法添加新元素--不可以添加原有的元素
set.add(new Person1("郭襄",100));
System.out.println(set);
}
}
Java单列集合框架之总结&体系图
单列集合体系图
Collection:所有单列集合的直接或间接接口,其指定了所有集合应该具备的基本功能。
List:元素可重复,有序,带索引
Set:元素不能重复,没有索引
ArrayList(重要) :底层是数组结构。ArrayList的出现替代了Vector,增删慢,查找快
LinkedList(重要):底层是链表结构。同时对元素的增删操作效率很高
HashSet(重要) :底层是哈希表结构。在不重复的基础上无序
LinkedHashSet:底层是哈希表结构结合链表结构。在不重复的基础上可预测迭代顺序