一、集合collection

1、存储数据的一种方式,更灵活更实用的框架
2、重点:蓝色边框是抽象类,蓝色心是实现类;image.png
3、

collection 不唯一 无序
List 不唯一 有序
Set 唯一 无序

1、List接口

List接口下的两个实现类:ArrayList和LinkedList

(1)、ArrayList存储数据

  1. //2,---创建ArrayList集合,并添加数据
  2. ArrayList list=new ArrayList();------要导包-------
  3. //add 向ArrayList中添加数据
  4. list.add("张三丰");
  5. list.add("郭靖");
  6. list.add("杨过");
  7. //---查看arraylist中的数据
  8. for(int i=0;i<list.size();i++){
  9. //get--- 从ArrayList中取值(index 下表索引)
  10. System.out.println(list.get(i));
  11. }
  12. //3,---contains 判断集合中是否有“李莫愁”--false/true
  13. System.out.println(list.contains("李莫愁"));
  14. //4,---把索引(下标)为0 的数据删除 remove(),括号里可以是下标也可以是字符串
  15. list.remove(0);

1、执行原理
/
arrayList初始化数组长度是10
数组长度不够用,当插入第11个数据的时候,数组进行扩容,
扩大到原来的1.5倍,数组长度是15
*/
2、ArrayList常用的方法
image.png

(2)、LinkedList存储数据

  1. LinkedList linkedlist=new LinkedList();------要导包-------
  2. //addFirst 将元素添加到列表的头部,
  3. linkedlist.add("a1");
  4. linkedlist.addFirst("a2");
  5. for(int i=0;i<linkedlist.size();i++){
  6. System.out.println(linkedlist.get(i));
  7. }
  8. System.out.println("-----------------");
  9. //removeFirst 删除集合中的第一个元素
  10. linkedlist.removeFirst();
  11. for(int i=0;i<linkedlist.size();i++){
  12. System.out.println(linkedlist.get(i));
  13. }
  14. }

1、执行原理
/
Node类,三个重要属性,
item(存放的是元素数据)
next(指向下一个链表节点)
prev(指向下一个链表节点)
add(a1)
Node1(item=a1 next=Node2 prev=null);
add(a2)
Node1(item=a1 next=Node2 prev=null);
Node2(item=a2 next=null prev=Node1);
add(a3)
Node1(item=a1 next=Node2 prev=null);
Node2(item=a2 next=Node3 prev=Node1);
Node3(item=a3 next=null prev=Node2);
remove(a2)
Node1(item=a1 next=Node3 prev=null);
Node3(item=a3 next=null prev=Node1);
/
2、LinkedList常用方法
image.png
3、何时实用两者或者两者之间的关系
(1)、ArrayList:元素个数不确定,需要遍历数组
(2)、LinkedList:元素个数不确定,需要在列表的头或者尾添加、删除元素
(3)、两者均是List接口的实现类
(4)、底层数据结构不同,ArrayList对象实现了可变大小的数组;LinkedList类用于创建双向链表数据结构
(5)、一般来讲,在查找效率方面,ArrayList要快于LinkedList;而在插入效率方面,LinkedList要高于ArrayList;
5、下面用例题来介绍ArrayList和LinkedList的用法
首先要建一个类,新闻标题类,存储的属性有ID,名称,和作者;提供共有的get和set方法,提供有参和无参构 造方法
其次

  1. 、、、ArrayList应用、、、
  2. public static void main(String[] args) {
  3. //创建存储新闻标题的集合对象
  4. ArrayList newsTitleList=new ArrayList();
  5. //按照顺序依次添加标题
  6. newsTitleList.add(new NewTitle(1, "汽车", "管理员"));
  7. newsTitleList.add(new NewTitle(2, "高考", "管理员"));
  8. newsTitleList.add(new NewTitle(3,"商业","zyz"));
  9. newsTitleList.add(new NewTitle(4,"建筑","管理员"));
  10. newsTitleList.add(new NewTitle(5,"餐饮","管理员"));
  11. //获取新闻标题的总数
  12. System.out.println("新闻标题的数量为:"+newsTitleList.size()+"条");
  13. //遍历集合对象
  14. System.out.println("新闻标题名称为:");
  15. for(int i=0;i<newsTitleList.size();i++){
  16. NewTitle title=(NewTitle)newsTitleList.get(i);
  17. System.out.println("新闻的id是:"+title.getID());
  18. System.out.println("新闻的名称是:"+title.getName());
  19. System.out.println("新闻的作者是:"+title.getMain());
  20. System.out.println("------------------");
  21. }
  22. 、、、LinkedList应用、、、
  23. public static void main(String[] args) {
  24. LinkedList linkedlist=new LinkedList();
  25. linkedlist.add(new NewTitle(1,"11=11=11","高阳"));
  26. linkedlist.add(new NewTitle(2,"22=22=22","孙琦"));
  27. linkedlist.add(new NewTitle(3,"33=33=33","欧阳11"));
  28. System.out.println("标题条数是:"+linkedlist.size());
  29. System.out.println("新闻标题名称为:");
  30. for(int i=0;i<linkedlist.size();i++){
  31. NewTitle title=(NewTitle)linkedlist.get(i);
  32. System.out.println("新闻的id是:"+title.getID());
  33. System.out.println("新闻的名称是:"+title.getName());
  34. System.out.println("新闻的作者是:"+title.getMain());
  35. System.out.println("------------------");
  36. }
  37. }

2、Set接口

1、HashSet实现类

1、创建集合对象
Set set=new HashSet();
:意思是泛型,也就是规定集合存放的类型
2、当定义的数据有两个是一样的,set.add(s1)加进去,会变成一个数据,即不重复数据
3、比如说定义了User类,其中有ID和name属性以及get/set方法和有参/无参构造方法
那么,//在插入user2的时候,equals进行比较判断set集合中是否存在元素——执行原理
//user中没有重写equals,默认采用Object中的比较(==比较的 是内存地址)
//如何解决这样的问题,要在user中重写equals方法
4、以下代码解决上述问题

  1. 测试类主方法内
  2. List<String> list=new ArrayList<String>();
  3. Set<User> set=new HashSet<User>();
  4. User user1=new User(1,"张三");
  5. User user2=new User(1,"张三");
  6. User user3=new User(2,"李四");
  7. User user4=new User(0,"王五");
  8. set.add(user1);
  9. set.add(user2);
  10. set.add(user3);
  11. set.add(user4);
  12. System.out.println(set.size());
  13. //如果User类里面没有重写equals()方法和hashCode()方法,那么显示的是4,否则重写了方法就显示的是3
  14. //原因是,重写之后hashCode值相同,系统就认为是相同的元素,合二为一;
  15. User类以及重写
  16. public class User {
  17. private int ID;
  18. private String name;
  19. public int getID() {
  20. return ID;
  21. }
  22. public void setID(int iD) {
  23. ID = iD;
  24. }
  25. public String getName() {
  26. return name;
  27. }
  28. public void setName(String name) {
  29. this.name = name;
  30. }
  31. public User(int iD, String name) {
  32. super();
  33. ID = iD;
  34. this.name = name;
  35. }
  36. public User(){
  37. }
  38. public boolean equals(Object obj){
  39. if(this==obj){
  40. return true;
  41. }
  42. if(obj instanceof User){
  43. User user=(User)obj;
  44. if(this.ID==user.ID&&this.name.equals(user.name)){
  45. return true;
  46. }
  47. }
  48. return false;
  49. }
  50. @Override
  51. //重写equals方法时,一般都需要重写HashCode方法
  52. public int hashCode() {
  53. return ID;
  54. }
  55. }

5、set没有get方法,所以无法进行正常的循环遍历

2、遍历信息(遍历set)

(1)、迭代方式——增强型for循环
(2)、迭代方法——迭代器Iterator

  1. //1、迭代方式---增强型for循环
  2. for (User user : set) {
  3. System.out.println(user.getName());
  4. }
  5. System.out.println("-------------------");
  6. //2、迭代方法---迭代器Iterator
  7. Iterator<User> it=set.iterator();
  8. //it.hasNext()-->迭代器中下一个元素是否存在,存在返回true,不存在返回false
  9. while(it.hasNext()){
  10. //next()-->获得下一个元素
  11. User user=it.next();
  12. System.out.println(user.getName());
  13. }
  14. }

6image.png
7、collection、List、Set、Map接口的联系和区别??
8、ArrayList和LinkedList的异同之处以及各自的应用场合??
9、遍历集合的方法??
10、泛型集合用法和好处??

3、Map接口

1、Map接口存储一组成对的键(key)和值(value)对象。
2、map在进行put和get时,只能取key,根据key找value;也就是提供key到value的映射,通过key来检索。
3、

key 不要求有序 不允许重复
value 不要求有序 允许重复

4、Map接口的常用方法
image.png
5、创建集合对象
Map map=new HashMap();
6、map存放数据用put方法(key,value)

  1. map.put("CN", "中华人民共和国");
  2. map.put("US", "美利坚合众国");
  3. map.put("RU", "俄罗斯联邦");
  4. map.put("JP", "日本国")

7、map中存放重复的数据key,覆盖之前的value值;key值在map中是唯一的
map.put(“US”, “美国”);
这条代码会覆盖原来的“US”,“美利坚合众国”
8、//删除US
map.remove(“US”);
9、//从map中取数据,—>get(key)
System.out.println(map.get(“US”));
10、//size()返回map中元素的个数
System.out.println(map.size());
11、//返回键值key的集合 可以是无序的——-map.keySet();
两种方法:1、foreach增强循环
2、迭代器—-Iterator

  1. Set<String> keyset=map.keySet();
  2. System.out.println("----key的第一种方法-----");
  3. for (String string : keyset) {
  4. System.out.println(string);
  5. }
  6. System.out.println("---key的第二种方法-----");
  7. Iterator<String> it=keyset.iterator();
  8. while(it.hasNext()){
  9. System.out.println(it.next());
  10. }

12、//返回value的集合——map.values();

  1. Collection<String> valueCollection=map.values();
  2. System.out.println("---value----");
  3. Iterator<String> itValue=valueCollection.iterator();
  4. while(itValue.hasNext()){
  5. System.out.println(itValue.next());
  6. }

13、//判断是否存在该key
System.out.println(map.containsKey(“US”));

1、遍历map

1、方案一的第1种—-增强for循环

  1. //方案一1、
  2. System.out.println("--方案一--");
  3. System.out.println("----遍历1----");
  4. Set<String> set1=map.keySet();
  5. for (String s : set1) {
  6. System.out.println(s+"---"+map.get(s));
  7. }

2、方案一的第2种—-迭代器Iterator

  1. //方案一2、
  2. System.out.println("----遍历2----");
  3. Iterator<String> it1=set1.iterator();
  4. while(it1.hasNext()){
  5. String key1=it1.next();
  6. System.out.println(key1+"---"+map.get(key1));
  7. }

3、方案二的第1种—-map.entrySet();

  1. System.out.println("--方案二--");
  2. Set<Entry<String, String>> set2=map.entrySet();
  3. //方案二1、
  4. System.out.println("--------遍历①----------");
  5. for (Entry<String, String> entry : set2) {
  6. System.out.println(entry.getKey()+"-----"+entry.getValue());
  7. }

4、方案二的第2种—-Iterator> it2=set2.iterator();

  1. Set<Entry<String, String>> set2=map.entrySet();
  2. //方案二2、
  3. System.out.println("--------遍历②----------");
  4. Iterator<Entry<String, String>> it2=set2.iterator();
  5. while(it2.hasNext()){
  6. Entry<String, String> entry=it2.next();
  7. System.out.println( entry.getKey()+"----"+entry.getValue());
  8. }

2、HashMap底层原理

//16 数组初始化的大小,map(数组+链表(1.8红黑树))
//0.75扩容因子,第一次扩容—当容量超过12(16*0.75),进行数组扩容,扩容为原来的2倍;
//底层结构,数组和链表
//链表超过>=8(链表的长度)—>红黑树,】】少于6—>单向链表;

3、Map常用方法

image.png
练习
image.png

  1. Scanner input = new Scanner System .in);
  2. Map<String , Student> map=new HashMap<String, Student>();
  3. map.put("Jack",new Student("1001","张三"18));
  4. map.put("Tom",new Student("1002","李四"19));
  5. map.put("Ben",new Student("1003","王五"20));
  6. system.out.print("请输入要查询的英文名")
  7. String n=input.next();
  8. systen.out.print(map.get(n).getName()+map.get(n).getAge());

二、泛型

1、泛型接口:public class Students implements TestInterface
2、两个参数类型定义泛型类:

  1. public class GenericDemo<T,V> {
  2. private T a;
  3. private V b;
  4. public GenericDemo(T a, V b) {
  5. super();
  6. this.a = a;
  7. this.b = b;
  8. }
  9. public void showType(){
  10. System.out.println("a的类型是:"+a.getClass().getName());
  11. System.out.println("b的类型是:"+b.getClass().getName());
  12. }
  13. 测试
  14. public static void main(String[] args) {
  15. GenericDemo<String,Integer> gel =new GenericDemo<String,Integer>("jack", 23);
  16. gel.showType();
  17. }

3、定义泛型方法:

  1. //定义泛型方法
  2. public<Integer>void showSize(Integer o){
  3. System.out.println(o.getClass().getName());
  4. }
  5. 测试
  6. public static void main(String[] args) {
  7. GenericMethod gm=new GenericMethod();
  8. gm.showSize(10);
  9. }

4、父类泛型

  1. //父类泛型---农场类
  2. public class Farm<T> {
  3. protected int plantNum=0;//农作物种植数量
  4. //种植农作物的方法
  5. public void planCrop(T crop){
  6. plantNum++;
  7. }
  8. //子类果园继承父类泛型
  9. public class FruitFarm<T>extends Farm<T> {
  10. //重写种植农作物的方法
  11. public void planCrop(List<T> list){
  12. plantNum+=list.size();
  13. }

三、collections

collections是一个类,collection是一个接口
1、collections.sort();排序方法
2、Collections.binarySearch(list, “3”)寻找集合内元素所在位置
3、Collections.max(list);集合中最大值
4、Collections.min(list);集合中最小值
5、在student类中定义泛型接口,List里面添加Student型数据,排序前要在student类中重新compareTo方法,(根据什么来进行排序)

  1. public static void main(String[] args) {
  2. List<Student> list=new ArrayList<Student>();
  3. list.add(new Student(1003,"张三"));
  4. list.add(new Student(1002,"李四"));
  5. list.add(new Student(1001,"王五"));
  6. list.add(new Student(1004,"赵柳"));
  7. //需要重写compreTo方法
  8. Collections.sort(list);
  9. System.out.println("----排序后------");
  10. for (Student student : list) {
  11. System.out.println(student.getSno()+"---"+student.getName());
  12. }
  13. 重新compareTo()
  14. //重写compreTo方法
  15. public int compareTo(Student o) {
  16. //从小到大排序
  17. return this.sno-o.sno;
  18. //从大到小
  19. //return o.sno-this.sno;

6,约瑟夫环——杀人游戏

  1. public class KillGame {
  2. public static void main(String[] args) {
  3. KillGame game=new KillGame();
  4. System.out.println(game.game1(50));
  5. }
  6. public String game1(int num){
  7. //初始化集 合1,2,3,4,5
  8. List<String> list=new ArrayList<String>();
  9. for (int i = 1; i <= num; i++) {
  10. list.add(i+"");
  11. }
  12. //3,4,5,1,2
  13. int count=0;
  14. while(true){
  15. count++;
  16. if(count==3){
  17. count=0;
  18. }else{
  19. list.add(list.get(0));//往后移
  20. }
  21. list.remove(0);
  22. if(list.size()==1){
  23. break;
  24. }
  25. }
  26. return list.get(0);
  27. }
  28. public String game2(int num){
  29. List<String> list=new ArrayList<String>();
  30. //5,4,3,2,1
  31. for (int i = num; i >=1; i--) {
  32. list.add(i+"");
  33. }
  34. //2,3,4,5,1
  35. int count=0;
  36. while(true){
  37. for (int i =list.size()-1; i >=0; i--) {
  38. count++;
  39. if(count==3){
  40. list.remove(i);
  41. count=0;
  42. }
  43. }
  44. if(list.size()==1){
  45. break;
  46. }
  47. }
  48. return list.get(0);
  49. }
  50. }

四、总结

1、Collection 、List 、Set 、Map接口的联系和区别 ?
四种.png
2、ArrayList和LinkedList的异同之处及各自的应用场合 ?
AL.png
3、遍历集合的方法 ?
遍历list:3中
遍历set:增强for循环,迭代器
遍历map:3种
4、泛型集合用法及好处?
1.什么是泛型,泛型有什么用,为什么要用
1.1 泛型就是一种未知的类,将未知的类型声明在集合、对象上,泛型的默认类型为Object。
例如: ArrayList str = new ArrayList();
这是将String类型指定在str这个集合内,这个集合存储或者读取的类型只能为String类型。
1.2 使用泛型可以在传参的时候(使用占位符 ? 占位)不固定传入什么类型,即可通用类型,
如果不设置泛型的上限(例如:< ? extends List>)和下限(例如:<? super List>)。
1.3 使用泛型后对象或者集合内只能放入指定的数据类型,可以保证对象或者集合的安全性,减少类型的转换操作。

2.怎么使用泛型,泛型可以作用在什么位置
2.1 有以下几种使用场景以及放在那种位置
 泛型只能定义引用数据类型,而不能使用基本数据类型
 泛型类、泛型方法、泛型接口、泛型通配符
例如:作用在类上时( public class Animal { E pet; } ) , 泛型跟在类后边,可以指定用了泛型的类内部的 pet 的类型。
作用在对象上时( Animal str = new Animal(); ) , 泛型跟在类后边 , 使得对象类的的 pet 属性为 Dog类型。
作用在方法上时( public Animal getPet(){ return E ; } ), 如在类上没有声明泛型时,必须在返回值和访问修饰符之间声明。
作为方法入参时( public void setPet(E pet){ this.pet = pet ; } ), 如在类上没有声明泛型时,必须在返回值和访问修饰符之间声明。

3.使用泛型的好处
3.1 使用泛型后对象或者集合内只能放入指定的数据类型,避免出现对象或者集合内的对象在多态使用的时候出现类型转换异常(java.lang.ClassCastException),可以保证对象或者集合的安全性。
3.2 指定了类型后,对象、集合或方法内只能使用对应的类型,可以减少类型的转换操作(在没有指定类型是类型转换必须使用 instanceof 关键字来进行判定),缩减了代码了,方便了程序员。

下面以代码的形式讲解

  1. package com.jq;
  2. /**
  3. * 声明在类上时,写在类名后边
  4. * @param <E>
  5. */
  6. class Animal <E> {
  7. /**
  8. * 作为属性声明时,必须在类上声明泛型
  9. */
  10. E pet;
  11. /**
  12. * 作为参数或者返回值时,如果在类上没有声明,必须在访问修饰符和返回值之间
  13. * @param pet
  14. */
  15. public void setPet(E pet){
  16. this.pet = pet;
  17. }
  18. public E getPet(){
  19. return pet;
  20. }
  21. public <T> void call(T t){
  22. System.out.println( t.toString() );
  23. }
  24. }
  25. 复制代码

使用泛型实现时,实现类必须使用对应的泛型类。
实现类声明泛型跟接口指定泛型可以同时使用。

  1. package com.jq;
  2. /**
  3. * 作用在接口上,如果实现该接口时指定实现类型
  4. * @param <T>
  5. */
  6. public interface Animals<T>{
  7. void call(T t);
  8. }
  9. /**
  10. * 拉布拉多犬
  11. */
  12. /**
  13. * 使用泛型实现时,实现类必须使用对应的泛型类。
  14. * 实现类声明泛型跟接口指定泛型可以同时使用。
  15. *如下代码:
  16. */
  17. class LaBuLaDuo<T> implements Animals<String> {
  18. public void call(String s) {
  19. System.out.println( s );
  20. }
  21. }