Java集合知识总结

编程入门 行业动态 更新时间:2024-10-09 03:18:39

Java集合<a href=https://www.elefans.com/category/jswz/34/1769308.html style=知识总结"/>

Java集合知识总结

今天在看了好多个集合帖子后发现讲的都是一半一半的,这下就逼死我这个强迫症患者了.于是自己写点,有不足之处还望各位道友多多指点

一、Collection接口

1.Collection接口

1.java.util.Collection接口:

1.所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法
2.任意的单列集合都可以使用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(): 把集合中的元素,存储到数组中。
示例
public class Collection {public static void main(String[] args) {//创建集合对象,可以使用多态//Collection<String> coll = new ArrayList<>();Collection<String> coll = new HashSet<>();System.out.println(coll);//重写了toString方法  []
​/*public boolean add(E e):把给定的对象添加到当前集合中 。返回值是一个boolean值,一般都返回true,所以可以不用接收*/boolean b1 = coll.add("张三");System.out.println("b1:"+b1);//b1:trueSystem.out.println(coll);//[张三]coll.add("李四");coll.add("李四");coll.add("赵六");coll.add("田七");System.out.println(coll);//[张三, 李四, 赵六, 田七]
​/*public boolean remove(E e): 把给定的对象在当前集合中删除。返回值是一个boolean值,集合中存在元素,删除元素,返回true集合中不存在元素,删除失败,返回false*/boolean b2 = coll.remove("赵六");System.out.println("b2:"+b2);//b2:true
​boolean b3 = coll.remove("赵四");System.out.println("b3:"+b3);//b3:falseSystem.out.println(coll);//[张三, 李四, 田七]
​/*public boolean contains(E e): 判断当前集合中是否包含给定的对象。包含返回true不包含返回false*/boolean b4 = coll.contains("李四");System.out.println("b4:"+b4);//b4:true
​boolean b5 = coll.contains("赵四");System.out.println("b5:"+b5);//b5:false
​//public boolean isEmpty(): 判断当前集合是否为空。集合为空返回true,集合不为空返回falseboolean b6 = coll.isEmpty();System.out.println("b6:"+b6);//b6:false
​//public int size(): 返回集合中元素的个数。int size = coll.size();System.out.println("size:"+size);//size:3
​//public Object[] toArray(): 把集合中的元素,存储到数组中。Object[] arr = coll.toArray();for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}
​//public void clear() :清空集合中所有的元素。但是不删除集合,集合还存在coll.clear();System.out.println(coll);//[]System.out.println(coll.isEmpty());//true}
}

2.Collection工具类

java.utils.Collections是集合工具类,用来对集合进行操作。部分方法如下:

public static boolean addAll(Collection c, T…
elements):往集合中添加一些元素。
public static void shuffle(List<?> list) :打乱顺序:打乱集合顺序。

示例

​public class Collections {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("e");*/
​//public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。Collections.addAll(list,"a","b","c","d","e");
​System.out.println(list);//[a, b, c, d, e]
​//public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。Collections.shuffle(list);System.out.println(list);//[b, d, c, a, e], [b, d, c, a, e]}
}

public static void sort(List list):将集合中元素按照默认规则排序。
注意:
sort(List list)使用前提:
被排序的集合里边存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序的规则

public class Sort {public static void main(String[] args) {ArrayList<Integer> list01 = new ArrayList<>();list01.add(1);list01.add(3);list01.add(2);System.out.println(list01);//[1, 3, 2]
​//public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。Collections.sort(list01);//默认是升序
​System.out.println(list01);//[1, 2, 3]
​ArrayList<String> list02 = new ArrayList<>();list02.add("a");list02.add("c");list02.add("b");System.out.println(list02);//[a, c, b]
​Collections.sort(list02);System.out.println(list02);//[a, b, c]
​ArrayList<Person> list03 = new ArrayList<>();list03.add(new Person("张三",18));list03.add(new Person("李四",20));list03.add(new Person("王五",15));System.out.println(list03);//[Person{name='张三', age=18}, Person{name='李四', age=20}, Person{name='王五', age=15}]
​Collections.sort(list03);System.out.println(list03);}
}

Comparator和Comparable的区别
Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较的规则compareTo方法
Comparator:相当于找一个第三方的裁判,比较两个
Comparable接口位于java.lang包下;Comparator位于java.util包下 Comparable接口只提供了一个compareTo()方法;Comparator接口不仅提供了compara()方法,还提供了其他默认方法,如reversed()、thenComparing(),使我们可以按照更多的方式进行排序

如果要用Comparable接口,则必须实现这个接口,并重写comparaTo()方法;但是Comparator接口可以在类外部使用,通过将该接口的一个匿名类对象当做参数传递给Collections.sort()方法或者Arrays.sort()方法实现排序。Comparator体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。
Comparator的排序规则:
o1-o2:升序

public class Sort2 {public static void main(String[] args) {
​        ArrayList<Integer> list01 = new ArrayList<>();list01.add(1);list01.add(3);list01.add(2);System.out.println(list01);//[1, 3, 2]
​Collections.sort(list01, new Comparator<Integer>() {//重写比较的规则@Overridepublic int compare(Integer o1, Integer o2) {//return o1-o2;//升序return o2-o1;//降序}});
​System.out.println(list01);
​ArrayList<Student> list02 = new ArrayList<>();list02.add(new Student("李志",18));list02.add(new Student("李德轩",20));list02.add(new Student("方永泰",17));list02.add(new Student("段睿新",18));System.out.println(list02);
​/*Collections.sort(list02, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {//按照年龄升序排序return o1.getAge()-o2.getAge();}});*/
​//扩展:了解Collections.sort(list02, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {//按照年龄升序排序int result =  o1.getAge()-o2.getAge();//如果两个人年龄相同,再使用姓名的第一个字比较if(result==0){result =  o1.getName().charAt(0)-o2.getName().charAt(0);}return  result;}
​});
​System.out.println(list02);}
}
public class Person implements Comparable<Person>{private String name;private int age; ​public Person() {} ​public Person(String name, int age) {this.name = name;this.age = age;} ​@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", 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;} ​//重写排序的规则@Overridepublic int compareTo(Person o) {//return 0;//认为元素都是相同的//自定义比较的规则,比较两个人的年龄(this,参数Person)//return this.getAge() - o.getAge();//年龄升序排序return o.getAge() - this.getAge();//年龄升序排序} }
public class Student {private String name;private int age;
​public Student() {}
​public Student(String name, int age) {this.name = name;this.age = age;}
​@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", 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;}
}

二、Iterator迭代器、增强for循环、泛型

1.Iterator迭代器

java.util.Iterator接口:迭代器(对集合进行遍历)

常用的方法

boolean hasNext() 如果仍有元素可以迭代,则返回 true。
判断集合中还有没有下一个元素,有就返回true,没有就返回false E next() 返回迭代的下一个元素。取出集合中的下一个元素

**注意:**

Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊
Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象
Iterator iterator() 返回在此 collection 的元素上进行迭代的迭代器

迭代器的使用步骤(重点):

1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
2.使用Iterator接口中的方法hasNext判断还有没有下一个元素
3.使用Iterator接口中的方法next取出集合中的下一个元素

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
​
public class Iterator {public static void main(String[] args) {//创建一个集合对象Collection<String> coll = new ArrayList<>();//往集合中添加元素coll.add("姚明");coll.add("科比");coll.add("麦迪");coll.add("詹姆斯");coll.add("艾弗森");
​/*1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)注意:Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型*///多态  接口            实现类对象Iterator<String> it = coll.iterator();
​
​/*发现使用迭代器取出集合中元素的代码,是一个重复的过程所以我们可以使用循环优化不知道集合中有多少元素,使用while循环循环结束的条件,hasNext方法返回false*/while(it.hasNext()){String e = it.next();System.out.println(e);}System.out.println("----------------------");for(Iterator<String> it2 = coll.iterator();it2.hasNext();){String e = it2.next();System.out.println(e);}
​
​/* //2.使用Iterator接口中的方法hasNext判断还有没有下一个元素boolean b = it.hasNext();System.out.println(b);//true//3.使用Iterator接口中的方法next取出集合中的下一个元素String s = it.next();System.out.println(s);//姚明
​b = it.hasNext();System.out.println(b);s = it.next();System.out.println(s);
​b = it.hasNext();System.out.println(b);s = it.next();System.out.println(s);
​b = it.hasNext();System.out.println(b);s = it.next();System.out.println(s);b = it.hasNext();System.out.println(b);s = it.next();System.out.println(s);
​b = it.hasNext();System.out.println(b);//没有元素,返回falses = it.next();//没有元素,在取出元素会抛出NoSuchElementException没有元素异常System.out.println(s);*/}
}

2.增强for循环

增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写 是JDK1.5之后出现的新特性
Collectionextends Iterable:所有的单列集合都可以使用增强for public interface
Iterable实现这个接口允许对象成为 “foreach” 语句的目标。
增强for循环:用来遍历集合和数组 格式:
for(集合/数组的数据类型 变量名: 集合名/数组名){ sout(变量名); }

import java.util.ArrayList;
public class Foreach {public static void main(String[] args) {demo02();}
​//使用增强for循环遍历集合private static void demo02() {ArrayList<String> list = new ArrayList<>();list.add("aaa");list.add("bbb");list.add("ccc");list.add("ddd");for(String s : list){System.out.println(s);}}
​//使用增强for循环遍历数组private static void demo01() {int[] arr = {1,2,3,4,5};for(int i:arr){System.out.println(i);}}
}

3.泛型

import java.util.ArrayList;
import java.util.Iterator;
​
public class Generic {public static void main(String[] args) {show02();}
​/*创建集合对象,使用泛型好处:1.避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型2.把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)弊端:泛型是什么类型,只能存储什么类型的数据*/private static void show02() {ArrayList<String> list = new ArrayList<>();list.add("abc");//list.add(1);//add(java.lang.String)in ArrayList cannot be applied to (int)
​//使用迭代器遍历list集合Iterator<String> it = list.iterator();while(it.hasNext()){String s = it.next();System.out.println(s+"->"+s.length());}}
​/*创建集合对象,不使用泛型好处:集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据弊端:不安全,会引发异常*/private static void show01() {ArrayList list = new ArrayList();list.add("abc");list.add(1);
​//使用迭代器遍历list集合//获取迭代器Iterator it = list.iterator();//使用迭代器中的方法hasNext和next遍历集合while(it.hasNext()){//取出元素也是Object类型Object obj = it.next();System.out.println(obj);
​//想要使用String类特有的方法,length获取字符串的长度;不能使用  多态 Object obj = "abc";//需要向下转型//会抛出ClassCastException类型转换异常,不能把Integer类型转换为String类型String s = (String)obj;System.out.println(s.length());}}
}

①定义含有泛型的类

模拟ArrayList集合

泛型是一个未知的数据类型,当我们不确定什么什么数据类型的时候,可以使用泛型
泛型可以接收任意的数据类型,可以使用Integer,String,Student… 创建对象的时候确定泛型的数据类型

public class GenericClass<E> {private E name;
​public E getName() {return name;}
​public void setName(E name) {this.name = name;}
}
public class GenericClass {public static void main(String[] args) {//不写泛型默认为Object类型GenericClass gc = new GenericClass();gc.setName("只能是字符串");Object obj = gc.getName(); ​//创建GenericClass对象,泛型使用Integer类型GenericClass<Integer> gc2 = new GenericClass<>();gc2.setName(1); ​Integer name = gc2.getName();System.out.println(name); ​//创建GenericClass对象,泛型使用String类型GenericClass<String> gc3 = new GenericClass<>();gc3.setName("小明");String name1 = gc3.getName();System.out.println(name1);} }

②定义含有泛型的方法

泛型定义在方法的修饰符和返回值类型之间

格式:
修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
方法体;
}

含有泛型的方法,在调用方法的时候确定泛型的数据类型 传递什么类型的参数,泛型就是什么类型

public class GenericMethod {//定义一个含有泛型的方法public <M> void method01(M m){System.out.println(m);}
​//定义一个含有泛型的静态方法public static <S> void method02(S s){System.out.println(s);}
}

测试含有泛型的方法

public class DemoGenericMethod {public static void main(String[] args) {//创建GenericMethod对象GenericMethod gm = new GenericMethod();/*调用含有泛型的方法method01传递什么类型,泛型就是什么类型*/gm.method01(10);gm.method01("abc");gm.method01(8.8);gm.method01(true);gm.method02("静态方法,不建议创建对象使用");//静态方法,通过类名.方法名(参数)可以直接使用GenericMethod.method02("静态方法");GenericMethod.method02(1);}
}

定义含有泛型的接口

public interface GenericInterface<I> {public abstract void method(I i);
}

③定义含有泛型的接口的实现类

含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型 public interface Iterator {
E next(); } Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默认就是String

public final class Scanner implements Iterator<String>{public String next() {}
}
public class GenericInterfaceImpl1 implements GenericInterface<String>{@Overridepublic void method(String s) {System.out.println(s);}
}

含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走
就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型

public interface List<E>{boolean add(E e);E get(int index);
}
public class ArrayList<E> implements List<E>{public boolean add(E e) {}public E get(int index) {}
}
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {@Overridepublic void method(I i) {System.out.println(i);}
}

测试含有泛型的接口

public class Demo04GenericInterface {public static void main(String[] args) {//创建GenericInterfaceImpl1对象GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();gi1.method("字符串");
​//创建GenericInterfaceImpl2对象GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();gi2.method(10);
​GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();gi3.method(8.8);}
}

④泛型标识符

泛型的通配符:
?:代表任意的数据类型 使用方式:
不能创建对象使用
只能作为方法的参数使用 泛型的上限限定: ? extends E 代表使用的泛型只能是E类型的子类/本身 泛型的下限限定: ? super E 代表使用的泛型只能是E类型的父类/本身

public class Demo05Generic {public static void main(String[] args) {ArrayList<Integer> list01 = new ArrayList<>();list01.add(1);list01.add(2);
​ArrayList<String> list02 = new ArrayList<>();list02.add("a");list02.add("b");
​printArray(list01);printArray(list02);
​//ArrayList<?> list03 = new ArrayList<?>();}
​/*定义一个方法,能遍历所有类型的ArrayList集合这时候我们不知道ArrayList集合使用什么数据类型,可以泛型的通配符?来接收数据类型注意:泛型没有继承概念的*/public static void printArray(ArrayList<?> list){//使用迭代器遍历集合Iterator<?> it = list.iterator();while(it.hasNext()){//it.next()方法,取出的元素是Object,可以接收任意的数据类型Object o = it.next();System.out.println(o);}}
}
import java.util.ArrayList;
import java.util.Collection;
​
/*泛型的上限限定: ? extends E  代表使用的泛型只能是E类型的子类/本身泛型的下限限定: ? super E    代表使用的泛型只能是E类型的父类/本身*/
public class Demo06Generic {public static void main(String[] args) {Collection<Integer> list1 = new ArrayList<Integer>();Collection<String> list2 = new ArrayList<String>();Collection<Number> list3 = new ArrayList<Number>();Collection<Object> list4 = new ArrayList<Object>();
​getElement1(list1);//getElement1(list2);//报错getElement1(list3);//getElement1(list4);//报错
​//getElement2(list1);//报错//getElement2(list2);//报错getElement2(list3);getElement2(list4);
​/*类与类之间的继承关系Integer extends Number extends ObjectString extends Object*/
​}// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类public static void getElement1(Collection<? extends Number> coll){}// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类public static void getElement2(Collection<? super Number> coll){}
}

三、几种数据结构的简单图解




四、几种集合的介绍与使用方法

1.List集合

①ArrayList集合

java.util.List接口 extends Collection接口

List接口的特点:

1.有序的集合,存储元素和取出元素的顺序是一致的(存储123 取出123)
2.有索引,包含了一些带索引的方法
​3.允许存储重复的元素

List接口中带索引的方法(特有)
- public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
- public E get(int index):返回集合中指定位置的元素。
- public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
- public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

注意:

操作索引的时候,一定要防止索引越界异常
IndexOutOfBoundsException:索引越界异常,集合会报
ArrayIndexOutOfBoundsException:数组索引越界异常
StringIndexOutOfBoundsException:字符串索引越界异常

public class List {public static void main(String[] args) {//创建一个List集合对象,多态List<String> list = new ArrayList<>();//使用add方法往集合中添加元素list.add("a");list.add("b");list.add("c");list.add("d");list.add("a");//打印集合System.out.println(list);//[a, b, c, d, a]  不是地址重写了toString
​//public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。//在c和d之间添加一个itheimalist.add(3,"itheima");//[a, b, c, itheima, d, a]System.out.println(list);
​//public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。//移除元素String removeE = list.remove(2);System.out.println("被移除的元素:"+removeE);//被移除的元素:cSystem.out.println(list);//[a, b, itheima, d, a]
​//public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。//把最后一个a,替换为AString setE = list.set(4, "A");System.out.println("被替换的元素:"+setE);//被替换的元素:aSystem.out.println(list);//[a, b, itheima, d, A]
​//List集合遍历有3种方式//使用普通的for循环for(int i=0; i<list.size(); i++){//public E get(int index):返回集合中指定位置的元素。String s = list.get(i);System.out.println(s);}System.out.println("-----------------");//使用迭代器Iterator<String> it = list.iterator();while(it.hasNext()){String s = it.next();System.out.println(s);}System.out.println("-----------------");//使用增强forfor (String s : list) {System.out.println(s);}
​String r = list.get(5);//IndexOutOfBoundsException: Index 5 out-of-bounds for length 5System.out.println(r);
​}
}

②LinkedList集合

java.util.LinkedList集合 implements List接口

LinkedList集合的特点:

1.底层是一个链表结构:查询慢,增删快
2.里边包含了大量操作首尾元素的方法

注意:使用LinkedList集合特有的方法,不能使用多态

public void addFirst(E e):将指定元素插入此列表的开头。
public void addLast(E e):将指定元素添加到此列表的结尾。
public void push(E e):将元素推入此列表所表示的堆栈。
public E getFirst():返回此列表的第一个元素。
public E getLast():返回此列表的最后一个元素。
public E removeFirst():移除并返回此列表的第一个元素。
public E removeLast():移除并返回此列表的最后一个元素。
public E pop():从此列表所表示的堆栈处弹出一个元素。
public boolean isEmpty():如果列表不包含元素,则返回true。

public class LinkedList {public static void main(String[] args) {show03();}
​/*- public E removeFirst():移除并返回此列表的第一个元素。- public E removeLast():移除并返回此列表的最后一个元素。- public E pop():从此列表所表示的堆栈处弹出一个元素。此方法相当于 removeFirst*/private static void show03() {//创建LinkedList集合对象LinkedList<String> linked = new LinkedList<>();//使用add方法往集合中添加元素linked.add("a");linked.add("b");linked.add("c");System.out.println(linked);//[a, b, c]
​//String first = linked.removeFirst();String first = linked.pop();System.out.println("被移除的第一个元素:"+first);String last = linked.removeLast();System.out.println("被移除的最后一个元素:"+last);System.out.println(linked);//[b]}
​/*- public E getFirst():返回此列表的第一个元素。- public E getLast():返回此列表的最后一个元素。*/private static void show02() {//创建LinkedList集合对象LinkedList<String> linked = new LinkedList<>();//使用add方法往集合中添加元素linked.add("a");linked.add("b");linked.add("c");
​//linked.clear();//清空集合中的元素 在获取集合中的元素会抛出NoSuchElementException
​//public boolean isEmpty():如果列表不包含元素,则返回true。if(!linked.isEmpty()){String first = linked.getFirst();System.out.println(first);//aString last = linked.getLast();System.out.println(last);//c}}
​/*- public void addFirst(E e):将指定元素插入此列表的开头。- public void addLast(E e):将指定元素添加到此列表的结尾。- public void push(E e):将元素推入此列表所表示的堆栈。此方法等效于 addFirst(E)。*/private static void show01() {//创建LinkedList集合对象LinkedList<String> linked = new LinkedList<>();//使用add方法往集合中添加元素linked.add("a");linked.add("b");linked.add("c");System.out.println(linked);//[a, b, c]
​//public void addFirst(E e):将指定元素插入此列表的开头。//linked.addFirst("www");linked.push("www");System.out.println(linked);//[www, a, b, c]
​//public void addLast(E e):将指定元素添加到此列表的结尾。此方法等效于 add()linked.addLast("com");System.out.println(linked);//[www, a, b, c, com]}
}

2.Set集合

①Set集合

java.util.Set接口 extends Collection接口

Set接口的特点:

1.不允许存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历

java.util.HashSet集合 implements Set接口

HashSet特点:

1.不允许存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
4.底层是一个哈希表结构(查询的速度非常的快)
public class Set {public static void main(String[] args) {Set<Integer> set = new HashSet<>();//使用add方法往集合中添加元素set.add(1);set.add(3);set.add(2);set.add(1);//使用迭代器遍历set集合Iterator<Integer> it = set.iterator();while (it.hasNext()){Integer n = it.next();System.out.println(n);//1,2,3}//使用增强for遍历set集合System.out.println("-----------------");for (Integer i : set) {System.out.println(i);}}
}

②哈希值

哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)

在Object类有一个方法,可以获取对象的哈希值 int hashCode() 返回该对象的哈希码值。
hashCode方法的源码:
public native int hashCode();
native:代表该方法调用的是本地操作系统的方法

public class Person extends  Object{//重写hashCode方法
​@Overridepublic int hashCode() {return  1;}
}
public class HashCode {public static void main(String[] args) {//Person类继承了Object类,所以可以使用Object类的hashCode方法Person p1 = new Person();int h1 = p1.hashCode();System.out.println(h1);//1967205423  | 1
​Person p2 = new Person();int h2 = p2.hashCode();System.out.println(h2);//42121758   |  1
​/*toString方法的源码:return getClass().getName() + "@" + Integer.toHexString(hashCode());*/System.out.println(p1);//com.itheima.demo03.hashCode.Person@75412c2fSystem.out.println(p2);//com.itheima.demo03.hashCode.Person@282ba1eSystem.out.println(p1==p2);//false
​/*String类的哈希值String类重写Obejct类的hashCode方法*/String s1 = new String("abc");String s2 = new String("abc");System.out.println(s1.hashCode());//96354System.out.println(s2.hashCode());//96354
​System.out.println("重地".hashCode());//1179395System.out.println("通话".hashCode());//1179395}
}

③HashSet集合

import java.util.HashSet;
/*** Set集合不允许存储重复元素的原理*/
public class HashSetSaveString {public static void main(String[] args) {//创建HashSet集合对象HashSet<String> set = new HashSet<>();String s1 = new String("abc");String s2 = new String("abc");set.add(s1);set.add(s2);set.add("重地");set.add("通话");set.add("abc");System.out.println(set);//[重地, 通话, abc]}
}
import java.util.HashSet;
/*HashSet存储自定义类型元素set集合报错元素唯一:存储的元素(String,Integer,...Student,Person...),必须重写hashCode方法和equals方法要求:同名同年龄的人,视为同一个人,只能存储一次*/
public class HashSetSavePerson {public static void main(String[] args) {//创建HashSet集合存储PersonHashSet<Person> set = new HashSet<>();Person p1 = new Person("小姐姐",18);Person p2 = new Person("小姐姐",18);Person p3 = new Person("小姐姐",19);System.out.println(p1.hashCode());//1967205423System.out.println(p2.hashCode());//42121758
​System.out.println(p1==p2);//falseSystem.out.println(p1.equals(p2));//falseset.add(p1);set.add(p2);set.add(p3);System.out.println(set);}
}
import java.util.Objects;
​
public class Person {private String name;private int age;
​public Person() {}
​public Person(String name, int age) {this.name = name;this.age = age;}
​@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age &&Objects.equals(name, person.name);}
​@Overridepublic int hashCode() {
​return Objects.hash(name, age);}
​@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", 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;}
}

④LinkedHashSet集合

import java.util.HashSet;
import java.util.LinkedHashSet;
​
/*java.util.LinkedHashSet集合 extends HashSet集合LinkedHashSet集合特点:底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序*/
public class Demo04LinkedHashSet {public static void main(String[] args) {HashSet<String> set = new HashSet<>();set.add("www");set.add("abc");set.add("abc");set.add("itcast");System.out.println(set);//[abc, www, itcast] 无序,不允许重复
​LinkedHashSet<String> linked = new LinkedHashSet<>();linked.add("www");linked.add("abc");linked.add("abc");linked.add("itcast");System.out.println(linked);//[www, abc, itcast] 有序,不允许重复}
}

3.可变参数

使用前提:

当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数. 使用格式:定义方法时使用
修饰符 返回值类型 方法名(数据类型…变量名){} 可变参数的原理:
可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
传递的参数个数,可以是0个(不传递),1,2…多个

public class Demo01VarArgs {public static void main(String[] args) {//int i = add();//int i = add(10);int i = add(10,20);//int i = add(10,20,30,40,50,60,70,80,90,100);System.out.println(i);
​method("abc",5.5,10,1,2,3,4);}
​/*可变参数的注意事项1.一个方法的参数列表,只能有一个可变参数2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾*//*public static void method(int...a,String...b){
错误写法}*/
​/*public static void method(String b,double c,int d,int...a){}*/
​//可变参数的特殊(终极)写法public static void method(Object...obj){
​}
​/*定义计算(0-n)整数和的方法已知:计算整数的和,数据类型已经确定int但是参数的个数不确定,不知道要计算几个整数的和,就可以使用可变参数add(); 就会创建一个长度为0的数组, new int[0]add(10); 就会创建一个长度为1的数组,存储传递来过的参数 new int[]{10};add(10,20); 就会创建一个长度为2的数组,存储传递来过的参数 new int[]{10,20};add(10,20,30,40,50,60,70,80,90,100); 就会创建一个长度为2的数组,存储传递来过的参数 new int[]{10,20,30,40,50,60,70,80,90,100};*/public static int add(int...arr){//System.out.println(arr);//[I@2ac1fdc4 底层是一个数组//System.out.println(arr.length);//0,1,2,10//定义一个初始化的变量,记录累加求和int sum = 0;//遍历数组,获取数组中的每一个元素for (int i : arr) {//累加求和sum += i;}//把求和结果返回return sum;}
}

4.Map集合

①Map集合

java.util.Map<k,v>集合

Map集合的特点:

1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2.Map集合中的元素,key和value的数据类型可以相同,也可以不同
3.Map集合中的元素,key是不允许重复的,value是可以重复的
4.Map集合中的元素,key和value是一一对应

java.util.HashMap<k,v>集合 implements Map<k,v>接口

HashMap集合的特点:

1.HashMap集合底层是哈希表:查询的速度特别的快
JDK1.8之前:数组+单向链表
JDK1.8之后:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度
2.hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致 1

java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合

LinkedHashMap的特点:

1.LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的

public class Map {public static void main(String[] args) {show04();}/*boolean containsKey(Object key) 判断集合中是否包含指定的键。包含返回true,不包含返回false*/private static void show04() {//创建Map集合对象Map<String,Integer> map = new HashMap<>();map.put("赵丽颖",168);map.put("杨颖",165);map.put("林志玲",178);
​boolean b1 = map.containsKey("赵丽颖");System.out.println("b1:"+b1);//b1:true
​boolean b2 = map.containsKey("赵颖");System.out.println("b2:"+b2);//b2:false}
​/*public V get(Object key) 根据指定的键,在Map集合中获取对应的值。返回值:key存在,返回对应的value值key不存在,返回null*/private static void show03() {//创建Map集合对象Map<String,Integer> map = new HashMap<>();map.put("赵丽颖",168);map.put("杨颖",165);map.put("林志玲",178);
​Integer v1 = map.get("杨颖");System.out.println("v1:"+v1);//v1:165
​Integer v2 = map.get("迪丽热巴");System.out.println("v2:"+v2);//v2:null}
​/*public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。返回值:Vkey存在,v返回被删除的值key不存在,v返回null*/private static void show02() {//创建Map集合对象Map<String,Integer> map = new HashMap<>();map.put("赵丽颖",168);map.put("杨颖",165);map.put("林志玲",178);System.out.println(map);//{林志玲=178, 赵丽颖=168, 杨颖=165}
​Integer v1 = map.remove("林志玲");System.out.println("v1:"+v1);//v1:178
​System.out.println(map);//{赵丽颖=168, 杨颖=165}
​//int v2 = map.remove("林志颖");//自动拆箱  NullPointerExceptionInteger v2 = map.remove("林志颖");System.out.println("v2:"+v2);//v2:null
​System.out.println(map);//{赵丽颖=168, 杨颖=165}}
​/*public V put(K key, V value):  把指定的键与指定的值添加到Map集合中。返回值:v存储键值对的时候,key不重复,返回值V是null存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值*/private static void show01() {//创建Map集合对象,多态Map<String,String> map = new HashMap<>();
​String v1 = map.put("李晨", "范冰冰1");System.out.println("v1:"+v1);//v1:null
​String v2 = map.put("李晨", "范冰冰2");System.out.println("v2:"+v2);//v2:范冰冰1
​System.out.println(map);//{李晨=范冰冰2}
​map.put("冷锋","龙小云");map.put("杨过","小龙女");map.put("尹志平","小龙女");System.out.println(map);//{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}}
}
Map集合的第一种遍历方式:通过键找值的方式

Map集合中的方法:

Set keySet() 返回此映射中包含的键的 Set 视图。

实现步骤:

1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
2.遍历set集合,获取Map集合中的每一个key
3.通过Map集合中的方法get(key),通过key找到value

public class KeySet {public static void main(String[] args) {//创建Map集合对象Map<String,Integer> map = new HashMap<>();map.put("李志",168);map.put("李德轩",165);map.put("方永泰",178);
​//1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中Set<String> set = map.keySet();
​//2.遍历set集合,获取Map集合中的每一个key//使用迭代器遍历Set集合Iterator<String> it = set.iterator();while (it.hasNext()){String key = it.next();//3.通过Map集合中的方法get(key),通过key找到valueInteger value = map.get(key);System.out.println(key+"="+value);}System.out.println("-------------------");//使用增强for遍历Set集合for(String key : set){//3.通过Map集合中的方法get(key),通过key找到valueInteger value = map.get(key);System.out.println(key+"="+value);}System.out.println("-------------------");//使用增强for遍历Set集合for(String key : map.keySet()){//3.通过Map集合中的方法get(key),通过key找到valueInteger value = map.get(key);System.out.println(key+"="+value);}}
}
Map集合遍历的第二种方式:使用Entry对象遍历

Map集合中的方法:

Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。

实现步骤:

1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
2.遍历Set集合,获取每一个Entry对象
3.使用Entry对象中的方法getKey()和getValue()获取键与值

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class EntrySet {public static void main(String[] args) {//创建Map集合对象Map<String,Integer> map = new HashMap<>();map.put("赵丽颖",168);map.put("杨颖",165);map.put("林志玲",178);
​//1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中Set<Map.Entry<String, Integer>> set = map.entrySet();
​//2.遍历Set集合,获取每一个Entry对象//使用迭代器遍历Set集合Iterator<Map.Entry<String, Integer>> it = set.iterator();while(it.hasNext()){Map.Entry<String, Integer> entry = it.next();//3.使用Entry对象中的方法getKey()和getValue()获取键与值String key = entry.getKey();Integer value = entry.getValue();System.out.println(key+"="+value);}System.out.println("-----------------------");for(Map.Entry<String,Integer> entry:set){//3.使用Entry对象中的方法getKey()和getValue()获取键与值String key = entry.getKey();Integer value = entry.getValue();System.out.println(key+"="+value);}}
}

HashMap存储自定义类型键值

Map集合保证key是唯一的:

作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一

public class HashMapSavePerson {public static void main(String[] args) {show02();}
​/*HashMap存储自定义类型键值key:Person类型Person类就必须重写hashCode方法和equals方法,以保证key唯一value:String类型可以重复*/private static void show02() {//创建HashMap集合HashMap<Person,String> map = new HashMap<>();//往集合中添加元素map.put(new Person("女王",18),"英国");map.put(new Person("秦始皇",18),"秦国");map.put(new Person("普京",30),"俄罗斯");map.put(new Person("女王",18),"毛里求斯");//使用entrySet和增强for遍历Map集合Set<Map.Entry<Person, String>> set = map.entrySet();for (Map.Entry<Person, String> entry : set) {Person key = entry.getKey();String value = entry.getValue();System.out.println(key+"-->"+value);}}
​/*HashMap存储自定义类型键值key:String类型String类重写hashCode方法和equals方法,可以保证key唯一value:Person类型value可以重复(同名同年龄的人视为同一个)*/private static void show01() {//创建HashMap集合HashMap<String,Person> map = new HashMap<>();//往集合中添加元素map.put("北京",new Person("张三",18));map.put("上海",new Person("李四",19));map.put("广州",new Person("王五",20));map.put("北京",new Person("赵六",18));//使用keySet加增强for遍历Map集合Set<String> set = map.keySet();for (String key : set) {Person value = map.get(key);System.out.println(key+"-->"+value);}}
}
import java.util.Objects;
​
public class Person {private String name;private  int age;
​public Person() {}
​public Person(String name, int age) {this.name = name;this.age = age;}
​@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
​@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age &&Objects.equals(name, person.name);}
​@Overridepublic int hashCode() {
​return Objects.hash(name, 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;}
}

②LinkedHashMap集合

java.util.LinkedHashMap<K,V> entends HashMap<K,V>

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。 底层原理:
哈希表+链表(记录元素的顺序)

public class LinkedHashMap {public static void main(String[] args) {HashMap<String,String> map = new HashMap<>();map.put("a","a");map.put("c","c");map.put("b","b");map.put("a","d");System.out.println(map);// key不允许重复,无序 {a=d, b=b, c=c}
​LinkedHashMap<String,String> linked = new LinkedHashMap<>();linked.put("a","a");linked.put("c","c");linked.put("b","b");linked.put("a","d");System.out.println(linked);// key不允许重复,有序 {a=d, c=c, b=b}}
}

③Hashtable集合

java.util.Hashtable<K,V>集合 implements Map<K,V>接口

Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快 HashMap集合(前面所有的集合):可以存储null值
Hashtable集合,不能存储null值,null键

Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
Hashtable的子类Properties依然活跃在历史舞台 Properties集合是一个唯一和IO流相结合的集合

public class Hashtable {public static void main(String[] args) {HashMap<String,String> map = new HashMap<>();map.put(null,"a");
​        map.put("b",null);map.put(null,null);System.out.println(map);//{null=null, b=null}
​Hashtable<String,String> table = new Hashtable<>();//table.put(null,"a");//NullPointerException//table.put("b",null);//NullPointerExceptiontable.put(null,null);//NullPointerException}
}

5.of方法

List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素 static List of(E…
elements)
使用前提:
当集合中存储的元素的个数已经确定了,不在改变时使用

注意:

1.of方法只适用于List接口,Set接口,Map接口,不适用于接接口的实现类
2.of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
3.Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常

public class Demo {public static void main(String[] args) {List<String> list = List.of("a", "b", "a", "c", "d");System.out.println(list);//[a, b, a, c, d]//list.add("w");//UnsupportedOperationException:不支持操作异常
​//Set<String> set = Set.of("a", "b", "a", "c", "d");//IllegalArgumentException:非法参数异常,有重复的元素Set<String> set = Set.of("a", "b", "c", "d");System.out.println(set);//set.add("w");//UnsupportedOperationException:不支持操作异常
​//Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20,"张三",19);IllegalArgumentException:非法参数异常,有重复的元素Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20);System.out.println(map);//{王五=20, 李四=19, 张三=18}//map.put("赵四",30);//UnsupportedOperationException:不支持操作异常}
}

更多推荐

Java集合知识总结

本文发布于:2024-02-13 16:56:39,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1759488.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:知识   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!