集合知识点综合

E
getFirst()
返回此列表中的第一个元素。
E
getLast()
返回此列表中的最后一个元素。
boolean
offer(E e)
将指定的元素添加为此列表的尾部(最后一个元素)。
boolean
offerFirst(E
e)
在此列表的前面插入指定的元素。
boolean
offerLast(E
e)
在此列表的末尾插入指定的元素。
E
peek()
检索但不删除此列表的头部(第一个元素)。
E
peekFirst()
检索但不删除此列表的第一个元素,如果此列表为空,则返回
null
E
peekLast()
检索但不删除此列表的最后一个元素,如果此列表为空,则返
null
E
poll()
检索并删除此列表的头部(第一个元素)。
E
pollFirst()
检索并删除此列表的第一个元素,如果此列表为空,则返回
null
E
pollLast()
检索并删除此列表的最后一个元素,如果此列表为空,则返回
null
一、内容回顾:
常见的数据结构:
栈: 先进后出 后进先出
队列:先进先出 后进后出
数组:查询快 增删慢
链表:单向链表 双向链表 循环链表
树形:二叉树 二叉查找树 二叉平衡树 红黑树
List
有序
可重复
可索引
可以存储多个 null
此实现不同步,不是线程安全的。
ArrayList :底层的数据结构 -- 数组 初始容量为 10 扩容因子是 1.5
二、 LinkedList
实现:双链表实现 允许 null 此实现不同步,不是线程安全的
特有的 API E
getFirst()
返回此列表中的第一个元素。
E
pop()
弹出此列表所代表的堆栈中的元素。
E
removeFirst()
从此列表中删除并返回第一个元素。
源码解读:
public class LinkedListDemo {
public static void main ( String [] args ) {
// List<String> l = new LinkedList<>();
LinkedList < String > list = new LinkedList <> ();
list . add ( "java" );
list . add ( "css" );
list . add ( "html" );
System . out . println ( list );
// 获取首尾元素
String first = list . getFirst ();
String last = list . getLast ();
System . out . println ( first + "-----" + last );
// 头插法和尾插法
list . offerFirst ( " 山西 " );
list . offerLast ( " 太原 " );
list . offer ( " 晋中 " );
System . out . println ( list );
// 检索首尾元素 检索不删除
String peekF = list . peekFirst ();
String peekL = list . peekLast ();
System . out . println ( peekF + "----" + peekL );
System . out . println ( list );
// 检索首尾元素 检索不删除
String pollF = list . pollFirst ();
String pollL = list . pollLast ();
System . out . println ( pollF + "----" + pollL );
System . out . println ( list );
// 弹出首元素 并从集合中删除
String popEle = list . pop ();
System . out . println ( popEle );
System . out . println ( list );
// 删除元素
list . removeFirst ();
list . removeLast ();
System . out . println ( list );
}
} 三、泛型
泛型:是 jdk1.5 中引入的特性,可以在编译阶段约束操作的数据类型,并进行类型检查。
泛型的格式: < 数据类型 > ;泛型又称为参数化类型。注意:泛型只能支持引用类型。
泛型的好处:
统一数据类型
把运行时期的问题提前到编译期间,避免了强制类型转换可能出现的异常,因为在编译节点类型就
已经确定了。
泛型的定义:
类:泛型类
接口:泛型接口
方法:泛型方法
3.1. 自定义泛型类
定义类的同时定义了泛型,这样的类 称之为泛型类
泛型类的格式:
泛型变量可以是任意标识符 常见的 E T K V
private static class Node < E > {
E item ;
Node < E > next ;
Node < E > prev ;
Node ( Node < E > prev , E element , Node < E > next ) {
this . item = element ;
this . next = next ;
this . prev = prev ;
}
}
public static void main ( String [] args ) {
List < String > list = new ArrayList <> ();
list . add ( "java" );
list . add ( "css" );
List list1 = new ArrayList (); // 如果定义的时候 没有指定泛型 则集合认为可添加的就是
Object
list1 . add ( 1 );
list1 . add ( "test" );
list1 . add ( true );
}
修饰符 class 类名 < 泛型变量 > { }
public class MyArrayList < E > {
} 作用 编译节点可以指定数据类型,类似集合的作用。
需求 : 模拟 ArrayList 集合自定义一个集合, MyArrayList 集合,完成添加和删除功能的泛型设计。
3.2. 自定义泛型方法
泛型方法的定义格式:
需求:给你任何一个类型的数组,都能返回他的内容,也就是实现 Arrays.toString (数组)的功能
public class MyArrayList < E > {
public ArrayList list = new ArrayList ();
public void add ( E e ){
list . add ( e );
}
public void remove ( E e ){
list . remove ( e );
}
@Override
public String toString () {
return "MyArrayList{" +
"list=" + list +
'}' ;
}
}
public class MyArrayListTest {
public static void main ( String [] args ) {
MyArrayList < String > ml = new MyArrayList <> ();
ml . add ( " 晋中理工 " );
ml . add ( " 山西太原 " );
System . out . println ( ml . toString ());
}
}
修饰符 < 泛型变量 > 方法的返回值(行参列表)
public class GenericDmeo1 {
public static void main ( String [] args ) {
String [] names = { " 小张 " , " 小王 " , " 小李 " };
printArr ( names );
Integer [] ages = { 23 , 12 , 33 };
printArr ( ages );
}
// 定义一个方法 可以将给定的数组 输出出来
public static < T > T [] getArray ( T [] array ){
return array ;
}
// [2,3,4,6,67,43]
public static < T > void printArr ( T [] arr ){
if ( arr != null ){ 下面的方法 不是泛型方法:
3.3. 泛型接口
格式:
作用:可以让实现类选择当前功能所需要操作的数据类型
需求:教务系统,提供一个接口,可以用来约束一定要完成数据(学生,老师)的增删改查操作
StringBuilder sb = new StringBuilder ( " " );
for ( int i = 0 ; i < arr . length ; i ++ ){
sb . append ( arr [ i ]). append ( i == arr . length - 1 ? "" : "," );
// if(i == arr.length-1){
// sb.append("");
// }else{
// sb.append(",");
// }
}
sb . append ( "]" );
System . out . println ( sb . toString ());
} else {
System . out . println ( arr );
}
}
}
public void test ( T t ){
}
修饰符 interface 接口名称 < 泛型变量 >{ }
// 泛型接口
public interface Data < E > {
void add ( E e );
void delete ( E e );
void update ( E e );
E queryById ( int id );
}
public class Student {
}
public class Teacher {
}
public class StudentData implements Data < Student > {
@Override
public void add ( Student student ) { 3.3. 泛型通配符 、上下限
通配符:?
?可以在使用泛型的时候,代表一切类型。
E,T,K,V 在定义泛型的时候使用
需求:开发一款赛车类游戏,所有的汽车都能一起参与比赛
}
@Override
public void delete ( Student student ) {
}
@Override
public void update ( Student student ) {
}
@Override
public Student queryById ( int id ) {
return null ;
}
}
public class TeacherData implements Data < Teacher > {
@Override
public void add ( Teacher teacher ) {
}
@Override
public void delete ( Teacher teacher ) {
}
@Override
public void update ( Teacher teacher ) {
}
@Override
public Teacher queryById ( int id ) {
return null ;
}
}
package cn.sxjzit.list;
import java.util.ArrayList;
import java.util.List; public class GenricDemo2 {
public static void main(String[] args) {
ArrayList<BMW> bmws = new ArrayList<>();
bmws.add(new BMW());
bmws.add(new BMW());
List<JieFang> jieFangs = new ArrayList<>();
jieFangs.add(new JieFang());
go(jieFangs);
go(bmws);
}
public static void go(List<? extends Car> cars){
}
}
// 父类
class Car{
}
class BENZ extends Car{
}
class BMW extends Car{
}
class JieFang extends Car{
}
? extends Car ? 必须是 Car 或者子类 泛型的上限
suerper Car ?必须是 Car 或者父类 泛型的下限
package cn . sxjzit . list ;
import java . util . ArrayList ;
import java . util . List ;
public class GenricDemo2 {
public static void main ( String [] args ) {
ArrayList < BMW > bmws = new ArrayList <> ();
bmws . add ( new BMW ());
bmws . add ( new BMW ());
List < JieFang > jieFangs = new ArrayList <> ();
jieFangs . add ( new JieFang ());
go ( jieFangs );
go ( bmws );
show ( bmws );
List < Car > cars = new ArrayList <> ();
cars . add ( new BENZ ());
cars . add ( new BMW ());
show ( cars );
}
// 泛型上限
public static void go ( List <? extends Car > cars ){ 泛型擦除
四、 Set 集合
Set 系列集合的特点:
元素不可重复
最多包含一个 null 元素
无序
不可索引
}
// 泛型的下限
public static void show ( List <? super BMW > bmws ){
}
}
// 父类
class Car {
}
class BENZ extends Car {
}
class BMW extends Car {
}
class JieFang extends Car {
}
public class GenricDemo3 {
public static void main ( String [] args ) throws NoSuchMethodException ,
InvocationTargetException , IllegalAccessException {
List < Integer > list = new ArrayList <> ();
list . add ( 12 );
list . add ( 23 );
// list.add(23.3);
// list.add("aa");
// 泛型只在编译阶段对类型进行检查
// 以下代码 利用反射技术,将集合中添加元素的时机放在运行阶段 在运行阶段 泛型已经不存
在 称为泛型擦除
list . getClass (). getMethod ( "add" , Object . class ). invoke ( list , " 山西 " );
list . getClass (). getMethod ( "add" , Object . class ). invoke ( list , 36.6 );
System . out . println ( list );
}
}
public class SetDemo {
public static void main ( String [] args ) {
// 1 创建 Set 集合
Set < String > set = new HashSet <> ();
//2 给集合添加元素 Set 集合实现类特点:
HashSet: 无序 不可重复 无索引 此实现不同步
LinkedHashSet: 有序 不可重复 无索引
TreeSet: 排序 不重复 无索引
4.1 HashSet
HashSet 集合的底层采用哈希表存储数据的。
哈希表是一种对于增删改查数据性能都较好的结构。
哈希表的组成:
jdk8 之前: 底层使用的数组 + 链表组成
jdk8 之后:底层采用的是数组 + 链表 + 红黑树组成。
哈希值:
jdk 根据对象计算得出的存储的地址,按照某种规则算出来的 int 类型的数值。
hashCode 返回对象的哈希值。
哈希值的特点:
对同一个对象多次调用 hashCode() 方法 返回的哈希值是相同的。
默认的情况下:不同对象的哈希值是不同的。
4.2 hashSet 底层的存储结构:
set . add ( "java" );
set . add ( "css" );
set . add ( "html" );
set . add ( "java" );
set . add ( "java" );
set . add ( null );
set . add ( null );
System . out . println ( set );
}
}
// 哈希值
String name = "Chinese";
System.out.println(name.hashCode());
System.out.println(name.hashCode());
String name1 = "Chinese";
System.out.println(name1.hashCode());
System.out.println(name1.hashCode()); JDK8 之前版本的底层原理:
当我们调用无参构造创建 hashSet 集合的时候,默认创建一个长度为 16 的数组。
添加元素时,根据元素的哈希值与数组的长度进行计算,从而得出元素对应的存储位置(哈希算
法)
判断当前计算出的位置是否为 null ,如果为 null ,直接存入。
如果位置不为 null ,表示有元素,需要调用 equals 方法比较:
如果一样,则不存,如果不一样,则存入数组。
jdk8 以前:新元素占据旧元素的位置,指向旧元素
jdb8 及其以后:新元素挂在旧元素的下边
结论:哈希表是一种对于增删改性能都较好的结构
jdk8 及其以后的版本的底层原理:
底层结构:哈希表(数组 链表 红黑树的结合体)
当挂在元素下边的数据过多的时候,查询的性能降低,从 jdk8 开始,当链表的长度超过 8 的时候,
自动的将链表转换为红黑树
红黑树的引入,进一步提高了数据的操作性能。
4.3 HashSet 元素去重的原理
首先判断元素的 hashcode 值是否相同,如果不同,则不重复;如果相同,则需要进一步调用他的 equals
方法进行比较,如果返回的 true ,则认为元素重复,不存;否则则认为不同,挂在元素的下边。
案例:使用 hashSet 存储自定义对象(学生对象)。
public class Student {
private String name;
private int age;
private String sex;
public Student() {
}
public Student(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
} 4.4 实现类: LinkedHashSet
特点:有序 不重复 无索引
有序指的是存入的顺序和取出的顺序一致。
原理:底层数据结构依然是哈希表,只是每个元素又额外地多了一个双链表的机制记录存储的顺序。
4.5 TreeSet
public class SetDemo2 {
public static void main(String[] args) {
Set<Student> sets = new HashSet<>();
Student s1 = new Student(" 张三 ",22," ");
Student s2 = new Student(" 张三 ",23," ");
Student s3 = new Student(" 张三 ",20," ");
System.out.println(s1.hashCode()+"------------"+s2.hashCode()+"----------
-"+s3.hashCode());
sets.add(s1);
sets.add(s2);
sets.add(s3);
System.out.println(sets);
}
}
public class SetDemo3 {
public static void main(String[] args) {
Set<String> sets = new LinkedHashSet<>();
sets.add("java");
sets.add("html");
sets.add("css");
sets.add("java");
sets.add("css");
sets.add(null);
sets.add(null);
System.out.println(sets);
}
}
public class SetDemo4 {
public static void main(String[] args) {
Set<Integer> sets = new TreeSet<>();
sets.add(23);
sets.add(22);
sets.add(24);
sets.add(8);
System.out.println(sets);
Set<String> sets1= new TreeSet<>();
sets1.add("java");
sets1.add("css");
sets1.add("about");
sets1.add("UI");
sets1.add("python");
sets1.add("java"); 特点:不重复 无索引 可排序。
默认:按照元素的大小顺序进行升序排列。
TreeSet 实例使用其 compareTo (或 compare )方法执行所有元素比较,对元素进行排序
排序方式:自然排序 定制排序
4.5.1. 自然排序
存入 TreeSet 集合中的元素 必须实现 Comparable ,通过重写 compareTo ,指定改对象的排序规则。
System.out.println(sets1);
Set<String> sets2 = new TreeSet<>();
// 汉字是按照 unincode 码进行排序
sets2.add(" 李四 ");
sets2.add(" 王五 ");
sets2.add(" 张三 ");
sets2.add(" 张四 ");
System.out.println((int)' ');//unincode
System.out.println((int)' ');//unincode
System.out.println(sets2);
}
}
public class Student implements Comparable < Student > {
private String name ;
private int age ;
private String sex ;
public Student () {
}
public Student ( String name , int age , String sex ) {
this . name = name ;
this . age = age ;
this . sex = sex ;
}
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 ;
} public String getSex () {
return sex ;
}
public void setSex ( String sex ) {
this . sex = sex ;
}
@Override
public boolean equals ( Object o ) {
if ( this == o ) return true ;
if ( o == null || getClass () != o . getClass ()) return false ;
Student student = ( Student ) o ;
return age == student . age && Objects . equals ( name , student . name ) &&
Objects . equals ( sex , student . sex );
}
@Override
public int hashCode () {
return Objects . hash ( name , age , sex );
}
@Override
public String toString () {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}' ;
}
@Override
public int compareTo ( Student o ) {
return this . getAge () - o . getAge ();
}
}
TreeSet 中 判断元素是否重复,主要判断依据是根据比较器的结果来判定。
Set < Student > sets3 = new TreeSet <> ();
Student s1 = new Student ( " 张三 " , 22 , " " );
Student s2 = new Student ( " 李四 " , 23 , " " );
Student s3 = new Student ( " 田七 " , 20 , " " );
Student s4 = new Student ( " 李四 " , 23 , " " );
Student s5 = new Student ( " 王五 " , 20 , " " );
sets3 . add ( s1 );
sets3 . add ( s2 );
sets3 . add ( s3 );
sets3 . add ( s4 );
sets3 . add ( s5 );
System . out . println ( sets3 ); 4.5.2 定制排序
在创建集合容器的时候,指定所使用的比较器
练习:将班级中学生的成绩保存起来,需要根据学生的成绩由高到低进行排序。如果成绩相同,则按照
姓名排序,如果姓名相同,则按照年龄排序。用两种方式:自然排序和定制排序两种方式实现。
4.6 Collection 体系的特点 使用场景总结
1 如果希望元素可重复,又有索引,索引查询快?
ArratList 基于数组的 使用最多。
2 如果希望元素可以重复,又有索引,增删首尾操作快?
LinkedList 基于链表的
// 首先根据姓名进行比较,如果姓名相同,在根据年龄进行排序
@Override
public int compareTo ( Student o ) {
// int res = 0;
// if(this.getName().compareTo( o.getName()) == 0) {
// res = -(this.getAge() - o.getAge());
// }else{
// res = this.getName().compareTo( o.getName());
// }
return this . getName (). compareTo ( o . getName ()) == 0 ? this . getAge () -
o . getAge (): this . getName (). compareTo ( o . getName ());
}
}
public static void main ( String [] args ) {
Set < Apple > set = new TreeSet <> ( new Comparator < Apple > () {
@Override
public int compare ( Apple o1 , Apple o2 ) {
return o1 . getWeight (). compareTo ( o2 . getWeight ());
}
});
Apple a1 = new Apple ( " 绿色 " , 2.2 );
Apple a2 = new Apple ( " 红色 " , 1.5 );
set . add ( a1 );
set . add ( a2 );
System . out . println ( set );
}
Set < Apple > set = new TreeSet <> (( o1 , o2 ) ->
o1 . getWeight (). compareTo ( o2 . getWeight ()));
Apple a1 = new Apple ( " 绿色 " , 2.2 );
Apple a2 = new Apple ( " 红色 " , 1.5 );
set . add ( a1 );
set . add ( a2 );
System . out . println ( set ); static <T>
boolean
replaceAll(List<T> list, T
oldVal, T newVal)
用列表替换列表中所有出现的
指定值。
static void
reverse(List<?> list)
反转指定列表中元素的顺序。
static void
shuffle(List<?> list)
使用默认的随机源随机置换指
定的列表。
static void
swap(List<?> list, int i, int j)
交换指定列表中指定位置的元
素。
3 如果希望增删改查都快,但是元素不重复, 无序 无索引?
HashSet, 基于哈希表
4 如果希望增删改查都快,但是元素不重复,有序,无索引?
LinkedHashset 基于哈希表和双链表
5 如果要对对象进行排序
TreeSet 基于红黑树
5 集合工具类 Collections
Collections 不属于集合,是用来操作集合的工具类
案例:斗地主游戏: 当启动在线扑克游戏的时候,应该提前准备好 54 张扑克牌,完成洗牌,发牌,排
序,逻辑
分析: 1 当系统启动的同时,需要准备好数据。将数据用静态代码块进行初始化。
2 洗牌:将所有牌随机打乱排序
public class CollectionsDemo {
public static void main ( String [] args ) {
List < String > names = new ArrayList <> ();
// names.add(" 楚留香 ");
// names.add(" 陆小凤 ");
// names.add(" 张无忌 ");
Collections . addAll ( names , " 楚留香 " , " 陆小凤 " , " 张无忌 " );
System . out . println ( names );
// 翻转输出顺序
Collections . reverse ( names );
System . out . println ( names );
// 随机排序
Collections . shuffle ( names );
System . out . println ( names );
// 排序
Collections . sort ( names );
System . out . println ( names );
// 交换两个元素的顺序
Collections . swap ( names , 1 , 2 );
System . out . println ( names );
}
} 3 定义三个玩家,一次发出 51 张牌。
4 给玩家的牌进行排序
5 输出每个玩家的牌的数据。
public class Card {
private String color;
private String size;
private int index;
public Card() {
}
public Card(String color, String size, int index) {
this.color = color;
this.size = size;
this.index = index;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Card card = (Card) o;
return index == card.index && Objects.equals(color, card.color) &&
Objects.equals(size, card.size);
}
@Override
public int hashCode() {
return Objects.hash(color, size, index); }
@Override
public String toString() {
return "Card{" +
"color='" + color + '\'' +
", size='" + size + '\'' +
", index=" + index +
'}';
}
}
public class GameDemo {
// 1 定义一个集合存储 54 张牌
public static List<Card> allCard = new ArrayList<>();
static {
//2 定义拍的点数 个数
String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
//3 定义花色
String[] colors = {"♠","♣","♦","♥"};
//4 点数和花色的组合
int index = 0;// 记录牌的大小
for(String size : sizes){
index++;
for(String color :colors){
// 5 封装成一个牌对象
Card c= new Card(color,size,index);
// 存储到集合中
allCard.add(c);
}
}
// 7 将大王小王存入集合
Card c1 = new Card(""," 大王 ",++index);
Card c2 = new Card(""," 小王 ",++index);
Collections.addAll(allCard,c1,c2);
System.out.println(allCard);
}
public static void main(String[] args) {
// 8 洗牌
Collections.shuffle(allCard);
System.out.println(allCard);
// 9 发牌
// 定义三个集合 表示三个人。
// 10 开始发牌
for(int i = 0 ; i < allCard.size();i++){
Card c = allCard.get(i);
if(i % 3 ==0 ){// 给第一个人
}else if(i % 3 == 1){// 给第 2 个人
}else{// 给第 3 个人
}
} }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值