集合
集合和数组的特点对比
集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以发生改变
集合和数组的区别:
共同点:都是存储数据的容器
不同点:
1.数组的长度是不可变的;集合的长度是可变的。
2.数组可以存基本数据类型和引用数据类型;
集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类。
如果存储的数据,长度经常发生改变,推荐使用集合
集合类体系结构
Collection
Collection集合概述
是单列集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素。
JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
创建Collection集合的对象
多态的方式
具体的实现类ArrayList
Collection 集合常用方法
boolean add(E e) 添加元素
boolean remove(Object o) 从集合中移除指定的元素
boolean removeif(Object o) 根据条件进行删除
void clear() 清空集合
boolean contains(Object o) 判断集合中是否存在指定的元素
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中元素的个数
1 public class MyCollectonDemo { 2 public static void main(String[] args) { 3 Collection<String> collection = new ArrayList<>(); 4 //boolean add(E e) 添加元素 5 collection.add("aaa"); 6 collection.add("bbb"); 7 8 //boolean remove(Object o) 从集合中移除指定的元素 9 boolean result1 = collection.remove("aaa"); 10 System.out.println(result1); //true 11 12 //boolean removeif(Object o) 根据条件进行删除 13 //removeif底层会遍历集合,得到集合中的每一个元素; 14 //s依次表示集合中的每一个元素,会把这每一个元素都到lambda表达式中去判断一下: 15 //如果返回的是true,则删除 16 //如果返回的是false,则保留不删除. 17 collection.removeIf( 18 (String s)->{ 19 return s.length() == 3; 20 } 21 ); 22 System.out.println(collection); 23 24 //void clear() 清空集合 25 collection.clear();//就是将集合中所有的元素全部删除. 26 System.out.println(collection); 27 28 //boolean contains(Object o) 判断集合中是否存在指定的元素 29 boolean result = collection.contains("a"); 30 System.out.println(result);//false 31 32 //boolean isEmpty() 判断集合是否为空 33 boolean result2 = collection.isEmpty(); 34 System.out.println(result2); 35 36 //int size() 集合的长度,也就是集合中元素的个数 37 int size = collection.size(); 38 System.out.println(size); 39 } 40 }
Collection 集合的遍历-迭代器
Iterator:迭代器,集合的专用遍历方式
Iterator<E> iterator():创建迭代器对象,该迭代器对象默认指向当前集合的0索引。
Iterator中的常用方法:
boolean hasNext():判断当前位置是否有元素可以被取出
E next():获取当前位置的元素。并将迭代器对象移向下一个索引位置。
1 public class MyCollectonDemo2 { 2 public static void main(String[] args) { 3 Collection<String> list = new ArrayList<>(); 4 list.add("a"); 5 list.add("b"); 6 list.add("c"); 7 list.add("d"); 8 list.add("e"); 9 10 //1,获得迭代器的对象 11 //迭代器对象一旦被创建出来,默认指向集合的0索引处 12 Iterator<String> it = list.iterator(); 13 14 //利用迭代器里面的方法进行遍历 15 //当前位置是否有元素可以被取出 16 //System.out.println(it.hasNext()); 17 //取出当前位置的元素 + 将迭代器往后移动一个索引的位置 18 //System.out.println(it.next()); 19 //System.out.println(it.next()); 20 21 while(it.hasNext()){ 22 System.out.println(it.next()); 23 } 24 } 25 }
Collection 集合的遍历-增强for循环
增强for:简化数组和Collection集合的遍历
它是JDK5之后出现的,其内部原理是一个Iterator迭代器
实现Iterable接口的类才可以使用迭代器和增强for
增强for的格式:
for(元素数据类型 变量名 : 数组或者Collection集合) {
//在此处使用变量即可,该变量就是元素
}
1 public static void main(String[] args) { 2 ArrayList<String> list = new ArrayList<>(); 3 list.add("a"); 4 list.add("b"); 5 6 //1.数据类型一定是集合或者数组中元素的类型 7 //2.str仅仅是一个变量名而已,在循环的过程中,依次表示集合或者数组中的每一个元素 8 //3.list就是要遍历的集合或者数组. 9 for(String str : list){ 10 System.out.println(str); 11 } 12 }
注意:修改第三方变量的值不会影响到集合中的元素
1 public static void main(String[] args) { 2 ArrayList<String> list = new ArrayList<>(); 3 list.add("a"); 4 list.add("b"); 5 6 for(String str : list){ 7 str = "q"; 8 System.out.println(str); //q q str是第三方变量 9 } 10 System.out.println(list); //[a, b] 集合中的值不变 11 }
三种循环的使用场景
如果需要操作索引,使用普通for循环
如果在遍历的过程中需要删除元素,请使用迭代器
如果仅仅想遍历,那么使用增强for
List
List集合概述
有序集合,这里的有序指的是存取顺序
用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
与Set集合不同,列表通常允许重复的元素
List集合特点
有序:存储和取出的元素顺序一致
有索引:可以通过索引操作元素
可重复:存储的元素可以重复
List集合特有方法
void add(int index,E element) 在此集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
1 public static void main(String[] args) { 2 List<String> list = new ArrayList<>(); 3 list.add("aaa"); 4 list.add("bbb"); 5 6 //void add(int index,E element) 在此集合中的指定位置插入指定的元素 7 //原来位置上的元素往后挪一个索引. 8 list.add(0,"qqq"); 9 System.out.println(list); //[qqq, aaa, bbb] 10 11 //在List集合中有两个删除的方法 12 //(常用)E remove(int index) 删除指定索引处的元素,返回被删除的元素 13 String s = list.remove(0); 14 System.out.println(s); //qqq 15 System.out.println(list); //[aaa, bbb] 16 //boolean remove(Object o) 从该列表中删除指定元素的第一个匹配项(如果存在),返回值表示当前元素是否删除成功 17 boolean r = list.remove("qqq"); 18 System.out.println(r); //false 19 System.out.println(list); //[aaa, bbb] 20 21 //E set(int index,E element) 修改指定索引处的元素,返回被修改的元素 22 //被替换的那个元素,在集合中就不存在了. 23 String result = list.set(0, "qqq"); 24 System.out.println(result); //aaa 25 System.out.println(list); //[qqq, bbb] 26 27 //E get(int index) 返回指定索引处的元素 28 String s1 = list.get(0); 29 System.out.println(s1); //qqq 30 }
List集合常用子类:ArrayList,LinkedList
ArrayList:底层数据结构是数组,查询快,增删慢
LinkedList:底层数据结构是链表,查询慢,增删快
ArrayList(底层:数组)
ArrayList的构造方法和成员方法
构造方法:public ArrayList() :创建一个空的集合对象
ArrayList<String> list = new ArrayList<>();
注:<E>是一种特殊的数据类型,泛型;E只能为引用数据类型
集合容器如果没有加入<E> 就可以存储任意数据类型
<E> 泛型:对集合容器存储的数据类型进行限制。是JDK5中引入的特性,它提供了编译时类型安全检测机制。
泛型的好处:
把运行时期的问题提前到了编译期间
避免了强制类型转换
成员方法:
public boolean add(E e) :将指定的元素追加到此集合的末尾
public void add(int index,E element) :在此集合中的指定位置插入指定的元素
public boolean remove(Object o) :删除指定的元素,返回删除是否成功
public E remove(int index) :删除指定索引处的元素,返回被删除的元素
public E set(int index,E element) :修改指定索引处的元素,返回被修改的元素
public E get(int index) :返回指定索引处的元素
public int size() :返回集合中的元素的个数
1 public class ArrayListDemo02 { 2 public static void main(String[] args) { 3 //创建集合 4 ArrayList<String> array = new ArrayList<>(); 5 //添加元素 6 array.add("hello"); 7 array.add("world"); 8 array.add("java"); 9 //public boolean remove(Object o):删除指定的元素,返回删除是否成功 10 // System.out.println(array.remove("world")); 11 // System.out.println(array.remove("javaee")); 12 //public E remove(int index):删除指定索引处的元素,返回被删除的元素 13 // System.out.println(array.remove(1)); 14 //IndexOutOfBoundsException 15 // System.out.println(array.remove(3)); 16 //public E set(int index,E element):修改指定索引处的元素,返回被修改的元素 17 // System.out.println(array.set(1,"javaee")); 18 //IndexOutOfBoundsException 19 // System.out.println(array.set(3,"javaee")); 20 //public E get(int index):返回指定索引处的元素 21 // System.out.println(array.get(0)); 22 // System.out.println(array.get(1)); 23 // System.out.println(array.get(2)); 24 //System.out.println(array.get(3)); 25 //public int size():返回集合中的元素的个数 26 System.out.println(array.size()); 27 //输出集合 28 System.out.println("array:" + array); 29 } 30 }
ArrayList的底层源码
ArrayList:底层数据结构是数组,查询快,增删慢。
通过空参构造:List<String> list = new ArrayList<>();在底层创建了一个长度为0的数组。
当调用:list.add("a");添加第一个元素时,ArrayList创建新的,长度为10的数组,默认初始化值为null
一般也认为ArrayList底层数组默认长度为10,数组在底层名字为:elementData;还存在一个变量:size,默认指向0索引位置(size:1.表示下次要操作的索引;2.表示数组中元素的个数)
自动扩容:当ArrayList添加完10个元素,size指向10索引时,再添加一个元素时,集合进行自动扩容。底层再次创建一个1.5倍长的数组,即10*1.5=15:创建一个长度为15的新数组,将原来所有的元素全部拷贝到新数组中,并且size的值不变,还是10。添加第11个元素时添加到size指向的位置。
集合删除元素
for循环删除
存储String的集合,内部存储(test,张三,李四,test,test)字符串,删除所有的test字符串
1 public static void main(String[] args) { 2 //1.创建集合对象 3 ArrayList<String> list=new ArrayList<>(); 4 //2.调用add方法,添加字符串 5 list.add("test"); 6 list.add("张三"); 7 list.add("李四"); 8 list.add("test"); 9 list.add("test"); 10 //3.遍历集合 11 for (int i = 0; i < list.size(); i++) { 12 String s = list.get(i); 13 //4.加入if判断,如果是test字符串,调用remove方法删除 14 if("test".equals(s)){ 15 list.remove(i); 16 i--; 17 } 18 } 19 System.out.println(list); 20 }
注:针对集合{test,张三,李四,test,test},遍历时首先指针指向索引0位置,判断是否为“test”,是则进行删除,同时剩余集合元素整体前移:“张三”变为0索引位置元素,【i++】使得指针指向1索引位置。如没有【i--】:删除完倒数第二个“test”后,最后一个“test”前移,指针指向下一位,会将最后一个“test”漏掉。所以在remove方法后,添加【i--】:删除完倒数第二个“test”后,指针前移至“李四”,再循环遍历执行【i++】,指针指向最后一个“test”并进行删除。
如需求为删除集合中所有指定的元素,要在remove后添加【i--】,否则可能会删除不完全。
迭代器删除
Iterator中的删除方法:
default void remove() 从底层集合中移除此迭代器返回的最后一个元素(可选操作)
1 public static void main(String[] args) { 2 ArrayList<String> list = new ArrayList<>(); 3 list.add("a"); 4 list.add("b"); 5 list.add("b"); 6 list.add("c"); 7 list.add("d"); 8 9 Iterator<String> it = list.iterator(); 10 while(it.hasNext()){ 11 String s = it.next(); 12 if("b".equals(s)){ 13 //指向谁,那么此时就删除谁. 14 it.remove(); 15 } 16 } 17 System.out.println(list); 18 }
LinkedList集合的特有功能(底层:链表)
public void addFirst(E e) 在该列表开头插入指定的元素
public void addLast(E e) 将指定的元素追加到此列表的末尾
public E getFirst() 返回此列表中的第一个元素
public E getLast() 返回此列表中的最后一个元素
public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素
1 public static void main(String[] args) { 2 LinkedList<String> list = new LinkedList<>(); 3 list.add("aaa"); 4 list.add("bbb"); 5 list.add("ccc"); 6 //public void addFirst(E e) 在该列表开头插入指定的元素 7 list.addFirst("qqq"); 8 System.out.println(list); //[qqq, aaa, bbb, ccc] 9 10 //public void addLast(E e) 将指定的元素追加到此列表的末尾 11 list.addLast("www"); 12 System.out.println(list); //[qqq, aaa, bbb, ccc, www] 13 14 //public E getFirst() 返回此列表中的第一个元素 15 //public E getLast() 返回此列表中的最后一个元素 16 String first = list.getFirst(); 17 String last = list.getLast(); 18 System.out.println(first); //qqq 19 System.out.println(last); //www 20 21 //public E removeFirst() 从此列表中删除并返回第一个元素 22 //public E removeLast() 从此列表中删除并返回最后一个元素 23 String first1 = list.removeFirst(); 24 System.out.println(first1); //qqq 25 String last1 = list.removeLast(); 26 System.out.println(last1); //www 27 System.out.println(list); //[aaa, bbb, ccc] 28 }
Set
Set集合特点
可以去除重复
存取顺序不一致
没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取、删除Set集合里面的元素
TreeSet(底层:红黑树)
TreeSet集合特点:
不包含重复元素的集合
没有带索引的方法
可以将元素按照规则进行排序
1 public static void main(String[] args) { 2 TreeSet<Integer> ts = new TreeSet<>(); 3 ts.add(3); 4 ts.add(4); 5 ts.add(1); 6 ts.add(2); 7 System.out.println(ts); //[1, 2, 3, 4] 8 }
自然排序Comparable的使用
构造方法:TreeSet() 构造一个新的空树集,根据其元素的自然顺序进行排序。
1、使用空参构造创建TreeSet集合
2、自定义的Student类实现Comparable接口
3、重写里面的compareTo方法
1 public class Student implements Comparable<Student>{ //2 2 private String name; 3 private int age; 4 5 public Student() { 6 } 7 ... 8 9 @Override 10 public int compareTo(Student o) { //3 11 //按照对象的年龄进行排序 12 //主要判断条件 13 int result = this.age - o.age; 14 //次要判断条件 15 result = result == 0 ? this.name.compareTo(o.getName()) : result; 16 return result; 17 } 18 }
1 public static void main(String[] args) { 2 TreeSet<Student> ts = new TreeSet<>(); //1 3 4 Student s1 = new Student("zhangsan",28); 5 Student s2 = new Student("lisi",28); 6 Student s3 = new Student("wangwu",29); 7 8 ts.add(s1); 9 ts.add(s2); 10 ts.add(s3); 11 System.out.println(ts); //[Student{name='lisi', age=28}, Student{name='zhangsan', age=28}, Student{name='wangwu', age=29}] 12 }
自然排序简单原理图
如果返回值为负数,表示当前存入的元素是较小值,存左边
如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
如果返回值为正数,表示当前存入的元素是较大值,存右边
String的compareTo方法:
int compareTo(String anotherString) 按字典顺序比较两个字符串。
1 public static void main(String[] args) { 2 String s1 = "aaa"; 3 String s2 = "ab"; 4 5 System.out.println(s1.compareTo(s2)); //-1 6 //首先比较第一个字母,如果第一个字母是一样的,那么继续比较后面的字母 7 //当不一样的时候,就拿着对应的码表值97,减去 b的码表值 98 ,认为a是比b要小的。 8 }
比较器排序Comparator的使用
构造方法:TreeSet(Comparator<? super E> comparator) 构造一个新的空树集,根据指定的比较器进行排序。
TreeSet的带参构造方法使用的是比较器排序对元素进行排序
比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
1 public static void main(String[] args) { 2 TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() { 3 @Override 4 public int compare(Teacher o1, Teacher o2) { 5 //o1表示现在要存入的那个元素;o2表示已经存入到集合中的元素 6 //主要条件 7 int result = o1.getAge() - o2.getAge(); 8 //次要条件 9 result = result == 0 ? o1.getName().compareTo(o2.getName()) : result; 10 return result; 11 } 12 }); 13 14 Teacher t1 = new Teacher("zhangsan",23); 15 Teacher t2 = new Teacher("lisi",22); 16 Teacher t3 = new Teacher("wangwu",24); 17 Teacher t4 = new Teacher("zhaoliu",24); 18 19 ts.add(t1); 20 ts.add(t2); 21 ts.add(t3); 22 ts.add(t4); 23 24 System.out.println(ts); //[Teacher{name='lisi', age=22}, Teacher{name='zhangsan', age=23}, Teacher{name='wangwu', age=24}, Teacher{name='zhaoliu', age=24}] 25 }
总结:
自然排序:自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序。
比较器排序:创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序。
在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,使用比较器排序
两种方式中,关于返回值的规则:
如果返回值为负数,表示当前存入的元素是较小值,存左边
如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
如果返回值为正数,表示当前存入的元素是较大值,存右边
HashSet(底层:哈希表)
HashSet集合特点:
底层数据结构是哈希表
对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以元素唯一
注:利用HashSet存储自定义元素,必须重写hashCode和equals方法。
哈希值
哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值:
public int hashCode():返回对象的哈希码值
对象的哈希值特点:
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同。
HashSet1.7版本原理解析
底层结构:哈希表。(数组、链表的结合体)。
1、通过空参构造:HashSet<String> hm = new HashSet<>();
创建一个默认长度16,默认加载因子为0.75的数组,数组名table;
2、如进行数据存储,先获取该元素的哈希值,并跟数组的长度计算得出应存入的索引;
3、如当前元素计算得出结果为4,需将该元素存入4索引位置;
判断当前位置是否为null,如果是null直接存入;
4、存第三个数据,计算得出结果依旧为4;当前位置不为null,表示有元素,则调用equals方法比较属性值;
5、如果一样,则不存;如果不一样,则存入数组,老元素挂在新元素下面。
6、继续存入元素,计算得出结果依旧为4,则先调用equals方法比较索引4位置链表的第一个元素的属性值,不相同就比较索引4位置链表的第二个元素,以此类推:如果一样,则不存;如果不一样,则存入数组,老元素挂在新元素下面。
7、当数组里面存了16*0.75=12个元素时,数组就会扩容为原先的两倍,即数组长度为16*2=32。
HashSet1.8版本原理解析
底层结构:哈希表。(数组、链表、红黑树的结合体)。
当挂在下面的元素过多,那么不利于查询,所以在JDK8以后,当链表长度超过8的时候,自动转换为红黑树。存储流程不变。
提高了查询及添加性能。
Map
Map集合概述
Interface Map<K,V> K:键的数据类型;V:值的数据类型
键不能重复,值可以重复
键和值是一一对应的,每一个键只能找到自己对应的值
(键 + 值)这个整体,我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”。
举例:学生的学号和姓名(xuehao01 张三)
创建Map集合的对象
多态的方式
具体的实现类HashMap
Map集合的常用方法
V put(K key,V value) 添加元素
如果要添加的键不存在,那么会把键值对都添加到集合中;
如果要添加的键是存在的,那么会覆盖原先的值,把原先值当做返回值进行返回。
V remove(Object key) 根据键删除键值对元素
void clear() 移除所有的键值对元素
boolean containsKey(Object key) 判断集合是否包含指定的键
boolean containsValue(Object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中键值对的个数
1 public static void main(String[] args) { 2 Map<String,String> map = new HashMap<>(); 3 //V put(K key,V value) 添加元素 4 map.put("xuehao01","张三"); 5 map.put("xuehao02","李四"); 6 map.put("xuehao03","王五"); 7 8 //如果要添加的键不存在,那么会把键值对都添加到集合中 9 //如果要添加的键是存在的,那么会覆盖原先的值,把原先值当做返回值进行返回。 10 String s1 = map.put("xuehao01", "aaa"); 11 System.out.println(s1); //张三 12 System.out.println(map); //{xuehao02=李四, xuehao03=王五, xuehao01=aaa} 13 14 //V remove(Object key) 根据键删除键值对元素 15 String s2 = map.remove("xuehao01"); 16 System.out.println(s2); //张三 17 System.out.println(map); //{xuehao02=李四, xuehao03=王五} 18 19 //void clear() 移除所有的键值对元素 20 map.clear(); 21 System.out.println(map); //{} 22 23 //boolean containsKey(Object key) 判断集合是否包含指定的键 24 boolean result1 = map.containsKey("xuehao01"); 25 System.out.println(result1); //true 26 27 //boolean containsValue(Object value) 判断集合是否包含指定的值 28 boolean result2 = map.containsValue("aaa"); //false 29 System.out.println(result2); 30 31 //boolean isEmpty() 判断集合是否为空 32 boolean empty1 = map.isEmpty(); 33 System.out.println(empty1); //false 34 35 //int size() 集合的长度,也就是集合中键值对的个数 36 int size = map.size(); 37 System.out.println(size); //3 38 }
Map集合的遍历-1
Set<K> keySet() 获取所有键的集合
V get(Object key) 根据键获取值
1 public static void main(String[] args) { 2 Map<String,String> map = new HashMap<>(); 3 map.put("xuehao01","张三"); 4 map.put("xuehao02","李四"); 5 map.put("xuehao03","王五"); 6 7 //获取到所有的键 8 Set<String> keys = map.keySet(); 9 //遍历Set集合得到每一个键 10 for (String key : keys) { 11 //通过每一个键key,来获取到对应的值 12 String value = map.get(key); 13 System.out.println(key + "---" + value); /*xuehao02---李四 14 xuehao03---王五 15 xuehao01---张三*/ 16 } 17 }
Map集合的遍历-2
Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合
K getKey() 获得键
V getValue() 获得值
1 public static void main(String[] args) { 2 //创建集合并添加元素 3 Map<String,String> map = new HashMap<>(); 4 map.put("xuehao01","张三"); 5 map.put("xuehao02","李四"); 6 map.put("xuehao03","王五"); 7 8 //Set集合中装的是键值对对象(Entry对象) 9 //而Entry里面装的是键和值 10 Set<Map.Entry<String, String>> entries = map.entrySet(); 11 for (Map.Entry<String, String> entry : entries) { 12 //得到每一个键值对对象 13 String key = entry.getKey(); 14 String value = entry.getValue(); 15 System.out.println(key + "---" + value); 16 } 17 }
Map集合的遍历-3
default void forEach(BiConsumer<super K,super V> action) 对此映射中的每个条目执行给定操作,直到处理完所有条目或操作引发异常。
1 public static void main(String[] args) { 2 HashMap<Student,String> hm = new HashMap<>(); 3 4 Student s1 = new Student("zhangsan",23); 5 Student s2 = new Student("lisi",22); 6 Student s3 = new Student("wangwu",22); 7 hm.put(s1,"江苏"); 8 hm.put(s2,"北京"); 9 hm.put(s3,"天津"); 10 11 hm.forEach( 12 (Student key, String value)->{ 13 System.out.println(key + "----" + value); /*Student{name='lisi', age=22}----北京 14 Student{name='zhangsan', age=23}----江苏 15 Student{name='wangwu', age=22}----天津*/ 16 } 17 ); 18 }
HashMap(底层:哈希表)
HashMap是Map里面的一个实现类。
没有额外需要学习的特有方法,直接使用Map里面的方法就可以了
HashMap跟HashSet一样底层是哈希表结构
依赖hashCode方法和equals方法保证键的唯一(和值无关)
如果键要存储的是自定义对象,需要重写hashCode和equals方法。(值要存储的是自定义对象,不需要重写)
TreeMap(底层:红黑树)
TreeMap是Map里面的一个实现类。
没有额外需要学习的特有方法,直接使用Map里面的方法就可以了
TreeMap跟TreeSet一样底层是红黑树结构
依赖自然排序或者比较器排序,对键进行排序(和值无关)
如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
1 public static void main(String[] args) { 2 TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() { 3 @Override 4 public int compare(Student o1, Student o2) { 5 int result = o1.getAge() - o2.getAge(); 6 result = result== 0 ? o1.getName().compareTo(o2.getName()) : result; 7 return result; 8 } 9 }); 10 11 Student s1 = new Student("xiaohei",23); 12 Student s2 = new Student("dapang",22); 13 Student s3 = new Student("xiaomei",22); 14 15 tm.put(s1,"江苏"); 16 tm.put(s2,"北京"); 17 tm.put(s3,"天津"); 18 19 tm.forEach( 20 (Student key, String value)->{ 21 System.out.println(key + "---" + value); 22 } 23 ); 24 }
可变参数
可变参数
就是形参的个数是可以变化的。
格式:修饰符 返回值类型 方法名(数据类型… 变量名) { }
范例:public static int sum(int… a) { }
可变参数注意事项:
这里的变量其实是一个数组
如果一个方法有多个参数,包含可变参数,可变参数要放在最后
1 public static void main(String[] args) { 2 int sum1 = getSum(1, 2, 3, 4, 5); 3 System.out.println(sum1); 4 } 5 6 //public static int getSum(int number,int... arr) { 7 public static int getSum(int... arr) { 8 int sum = 0; 9 for (int i = 0; i < arr.length; i++) { 10 sum = sum + arr[i]; 11 } 12 return sum; 13 }
创建不可变集合
在List、Set、Map接口中,都存在of方法,可以创建一个不可变的集合。
这个集合不能添加,不能删除,不能修改。可以结合集合的带参构造,实现集合的批量添加。
static<E> List<E> of(E…elements) 创建一个具有指定元素的List集合对象
static<E> Set<E> of(E…elements) 创建一个具有指定元素的Set集合对象
static<K,V> Map<K,V> of(E…elements) 创建一个具有指定元素的Map集合对象
在Map接口中,还有一个ofEntries方法可以提高代码的阅读性。首先会把键值对封装成一个Entry对象,再把这个Entry对象添加到集合当中。
static <K,V> Map<K,V> ofEntries(Map.Entry<extends K,extends V>... entries) 返回包含从给定条目中提取的键和值的不可修改的映射
1 public static void main(String[] args) { 2 // static <E> List<E> of(E…elements) 创建一个具有指定元素的List集合对象 3 List<String> list = List.of("a", "b", "c", "d"); 4 System.out.println(list); 5 6 //集合的批量添加。不需要写多个 list.add("aaa"); 7 //首先是通过调用List.of方法来创建一个不可变的集合,of方法的形参就是一个可变参数。 8 //再创建一个ArrayList集合,并把这个不可变的集合中所有的数据,都添加到ArrayList中。 9 ArrayList<String> list1 = new ArrayList<>(List.of("a", "b", "c", "d")); 10 System.out.println(list1); 11 12 //static <E> Set<E> of(E…elements) 创建一个具有指定元素的Set集合对象 13 //传递的参数当中,不能存在重复的元素。 14 Set<String> set = Set.of("a", "b", "c", "d"); 15 System.out.println(set); 16 17 //static <K , V> Map<K,V> of(E…elements) 创建一个具有指定元素的Map集合对象 18 Map<String, String> map = Map.of("zhangsan", "江苏", "lisi", "北京", "wangwu", "天津"); 19 System.out.println(map); 20 21 //static <K,V> Map<K,V> ofEntries(Map.Entry<extends K,extends V>... entries) 返回包含从给定条目中提取的键和值的不可修改的映射 22 Map<String, String> map = Map.ofEntries( 23 Map.entry("zhangsan", "江苏"), 24 Map.entry("lisi", "北京")); 25 System.out.println(map); 26 }