一、集合collection
1、存储数据的一种方式,更灵活更实用的框架
2、重点:蓝色边框是抽象类,蓝色心是实现类;
3、
| collection | 不唯一 | 无序 |
|---|---|---|
| List | 不唯一 | 有序 |
| Set | 唯一 | 无序 |
1、List接口
List接口下的两个实现类:ArrayList和LinkedList
(1)、ArrayList存储数据
//2,---创建ArrayList集合,并添加数据ArrayList list=new ArrayList();------要导包-------//add 向ArrayList中添加数据list.add("张三丰");list.add("郭靖");list.add("杨过");//---查看arraylist中的数据for(int i=0;i<list.size();i++){//get--- 从ArrayList中取值(index 下表索引)System.out.println(list.get(i));}//3,---contains 判断集合中是否有“李莫愁”--false/trueSystem.out.println(list.contains("李莫愁"));//4,---把索引(下标)为0 的数据删除 remove(),括号里可以是下标也可以是字符串list.remove(0);
1、执行原理
/
arrayList初始化数组长度是10
数组长度不够用,当插入第11个数据的时候,数组进行扩容,
扩大到原来的1.5倍,数组长度是15
*/
2、ArrayList常用的方法
(2)、LinkedList存储数据
LinkedList linkedlist=new LinkedList();------要导包-------//addFirst 将元素添加到列表的头部,linkedlist.add("a1");linkedlist.addFirst("a2");for(int i=0;i<linkedlist.size();i++){System.out.println(linkedlist.get(i));}System.out.println("-----------------");//removeFirst 删除集合中的第一个元素linkedlist.removeFirst();for(int i=0;i<linkedlist.size();i++){System.out.println(linkedlist.get(i));}}
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常用方法
3、何时实用两者或者两者之间的关系
(1)、ArrayList:元素个数不确定,需要遍历数组
(2)、LinkedList:元素个数不确定,需要在列表的头或者尾添加、删除元素
(3)、两者均是List接口的实现类
(4)、底层数据结构不同,ArrayList对象实现了可变大小的数组;LinkedList类用于创建双向链表数据结构
(5)、一般来讲,在查找效率方面,ArrayList要快于LinkedList;而在插入效率方面,LinkedList要高于ArrayList;
5、下面用例题来介绍ArrayList和LinkedList的用法
首先要建一个类,新闻标题类,存储的属性有ID,名称,和作者;提供共有的get和set方法,提供有参和无参构 造方法
其次
、、、ArrayList应用、、、public static void main(String[] args) {//创建存储新闻标题的集合对象ArrayList newsTitleList=new ArrayList();//按照顺序依次添加标题newsTitleList.add(new NewTitle(1, "汽车", "管理员"));newsTitleList.add(new NewTitle(2, "高考", "管理员"));newsTitleList.add(new NewTitle(3,"商业","zyz"));newsTitleList.add(new NewTitle(4,"建筑","管理员"));newsTitleList.add(new NewTitle(5,"餐饮","管理员"));//获取新闻标题的总数System.out.println("新闻标题的数量为:"+newsTitleList.size()+"条");//遍历集合对象System.out.println("新闻标题名称为:");for(int i=0;i<newsTitleList.size();i++){NewTitle title=(NewTitle)newsTitleList.get(i);System.out.println("新闻的id是:"+title.getID());System.out.println("新闻的名称是:"+title.getName());System.out.println("新闻的作者是:"+title.getMain());System.out.println("------------------");}、、、LinkedList应用、、、public static void main(String[] args) {LinkedList linkedlist=new LinkedList();linkedlist.add(new NewTitle(1,"11=11=11","高阳"));linkedlist.add(new NewTitle(2,"22=22=22","孙琦"));linkedlist.add(new NewTitle(3,"33=33=33","欧阳11"));System.out.println("标题条数是:"+linkedlist.size());System.out.println("新闻标题名称为:");for(int i=0;i<linkedlist.size();i++){NewTitle title=(NewTitle)linkedlist.get(i);System.out.println("新闻的id是:"+title.getID());System.out.println("新闻的名称是:"+title.getName());System.out.println("新闻的作者是:"+title.getMain());System.out.println("------------------");}}
2、Set接口
1、HashSet实现类
1、创建集合对象
Set
2、当定义的数据有两个是一样的,set.add(s1)加进去,会变成一个数据,即不重复数据
3、比如说定义了User类,其中有ID和name属性以及get/set方法和有参/无参构造方法
那么,//在插入user2的时候,equals进行比较判断set集合中是否存在元素——执行原理
//user中没有重写equals,默认采用Object中的比较(==比较的 是内存地址)
//如何解决这样的问题,要在user中重写equals方法
4、以下代码解决上述问题
测试类主方法内List<String> list=new ArrayList<String>();Set<User> set=new HashSet<User>();User user1=new User(1,"张三");User user2=new User(1,"张三");User user3=new User(2,"李四");User user4=new User(0,"王五");set.add(user1);set.add(user2);set.add(user3);set.add(user4);System.out.println(set.size());//如果User类里面没有重写equals()方法和hashCode()方法,那么显示的是4,否则重写了方法就显示的是3//原因是,重写之后hashCode值相同,系统就认为是相同的元素,合二为一;User类以及重写public class User {private int ID;private String name;public int getID() {return ID;}public void setID(int iD) {ID = iD;}public String getName() {return name;}public void setName(String name) {this.name = name;}public User(int iD, String name) {super();ID = iD;this.name = name;}public User(){}public boolean equals(Object obj){if(this==obj){return true;}if(obj instanceof User){User user=(User)obj;if(this.ID==user.ID&&this.name.equals(user.name)){return true;}}return false;}@Override//重写equals方法时,一般都需要重写HashCode方法public int hashCode() {return ID;}}
2、遍历信息(遍历set)
(1)、迭代方式——增强型for循环
(2)、迭代方法——迭代器Iterator
//1、迭代方式---增强型for循环for (User user : set) {System.out.println(user.getName());}System.out.println("-------------------");//2、迭代方法---迭代器IteratorIterator<User> it=set.iterator();//it.hasNext()-->迭代器中下一个元素是否存在,存在返回true,不存在返回falsewhile(it.hasNext()){//next()-->获得下一个元素User user=it.next();System.out.println(user.getName());}}
6
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接口的常用方法
5、创建集合对象
Map
6、map存放数据用put方法(key,value)
map.put("CN", "中华人民共和国");map.put("US", "美利坚合众国");map.put("RU", "俄罗斯联邦");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
Set<String> keyset=map.keySet();System.out.println("----key的第一种方法-----");for (String string : keyset) {System.out.println(string);}System.out.println("---key的第二种方法-----");Iterator<String> it=keyset.iterator();while(it.hasNext()){System.out.println(it.next());}
12、//返回value的集合——map.values();
Collection<String> valueCollection=map.values();System.out.println("---value----");Iterator<String> itValue=valueCollection.iterator();while(itValue.hasNext()){System.out.println(itValue.next());}
13、//判断是否存在该key
System.out.println(map.containsKey(“US”));
1、遍历map
1、方案一的第1种—-增强for循环
//方案一1、System.out.println("--方案一--");System.out.println("----遍历1----");Set<String> set1=map.keySet();for (String s : set1) {System.out.println(s+"---"+map.get(s));}
2、方案一的第2种—-迭代器Iterator
//方案一2、System.out.println("----遍历2----");Iterator<String> it1=set1.iterator();while(it1.hasNext()){String key1=it1.next();System.out.println(key1+"---"+map.get(key1));}
3、方案二的第1种—-map.entrySet();
System.out.println("--方案二--");Set<Entry<String, String>> set2=map.entrySet();//方案二1、System.out.println("--------遍历①----------");for (Entry<String, String> entry : set2) {System.out.println(entry.getKey()+"-----"+entry.getValue());}
4、方案二的第2种—-Iterator
Set<Entry<String, String>> set2=map.entrySet();//方案二2、System.out.println("--------遍历②----------");Iterator<Entry<String, String>> it2=set2.iterator();while(it2.hasNext()){Entry<String, String> entry=it2.next();System.out.println( entry.getKey()+"----"+entry.getValue());}
2、HashMap底层原理
//16 数组初始化的大小,map(数组+链表(1.8红黑树))
//0.75扩容因子,第一次扩容—当容量超过12(16*0.75),进行数组扩容,扩容为原来的2倍;
//底层结构,数组和链表
//链表超过>=8(链表的长度)—>红黑树,】】少于6—>单向链表;
3、Map常用方法

练习
Scanner input = new Scanner (System .in);Map<String , Student> map=new HashMap<String, Student>();map.put("Jack",new Student("1001","张三",18));map.put("Tom",new Student("1002","李四",19));map.put("Ben",new Student("1003","王五",20));system.out.print("请输入要查询的英文名")String n=input.next();systen.out.print(map.get(n).getName()+map.get(n).getAge());
二、泛型
1、泛型接口:public class Students
2、两个参数类型定义泛型类:
public class GenericDemo<T,V> {private T a;private V b;public GenericDemo(T a, V b) {super();this.a = a;this.b = b;}public void showType(){System.out.println("a的类型是:"+a.getClass().getName());System.out.println("b的类型是:"+b.getClass().getName());}测试public static void main(String[] args) {GenericDemo<String,Integer> gel =new GenericDemo<String,Integer>("jack", 23);gel.showType();}
3、定义泛型方法:
//定义泛型方法public<Integer>void showSize(Integer o){System.out.println(o.getClass().getName());}测试public static void main(String[] args) {GenericMethod gm=new GenericMethod();gm.showSize(10);}
4、父类泛型
//父类泛型---农场类public class Farm<T> {protected int plantNum=0;//农作物种植数量//种植农作物的方法public void planCrop(T crop){plantNum++;}//子类果园继承父类泛型public class FruitFarm<T>extends Farm<T> {//重写种植农作物的方法public void planCrop(List<T> list){plantNum+=list.size();}
三、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方法,(根据什么来进行排序)
public static void main(String[] args) {List<Student> list=new ArrayList<Student>();list.add(new Student(1003,"张三"));list.add(new Student(1002,"李四"));list.add(new Student(1001,"王五"));list.add(new Student(1004,"赵柳"));//需要重写compreTo方法Collections.sort(list);System.out.println("----排序后------");for (Student student : list) {System.out.println(student.getSno()+"---"+student.getName());}重新compareTo()//重写compreTo方法public int compareTo(Student o) {//从小到大排序return this.sno-o.sno;//从大到小//return o.sno-this.sno;
6,约瑟夫环——杀人游戏
public class KillGame {public static void main(String[] args) {KillGame game=new KillGame();System.out.println(game.game1(50));}public String game1(int num){//初始化集 合1,2,3,4,5List<String> list=new ArrayList<String>();for (int i = 1; i <= num; i++) {list.add(i+"");}//3,4,5,1,2int count=0;while(true){count++;if(count==3){count=0;}else{list.add(list.get(0));//往后移}list.remove(0);if(list.size()==1){break;}}return list.get(0);}public String game2(int num){List<String> list=new ArrayList<String>();//5,4,3,2,1for (int i = num; i >=1; i--) {list.add(i+"");}//2,3,4,5,1int count=0;while(true){for (int i =list.size()-1; i >=0; i--) {count++;if(count==3){list.remove(i);count=0;}}if(list.size()==1){break;}}return list.get(0);}}
四、总结
1、Collection 、List 、Set 、Map接口的联系和区别 ?
2、ArrayList和LinkedList的异同之处及各自的应用场合 ?
3、遍历集合的方法 ?
遍历list:3中
遍历set:增强for循环,迭代器
遍历map:3种
4、泛型集合用法及好处?
1.什么是泛型,泛型有什么用,为什么要用
1.1 泛型就是一种未知的类,将未知的类型声明在集合、对象上,泛型的默认类型为Object。
例如: ArrayList
这是将String类型指定在str这个集合内,这个集合存储或者读取的类型只能为String类型。
1.2 使用泛型可以在传参的时候(使用占位符 ? 占位)不固定传入什么类型,即可通用类型,
如果不设置泛型的上限(例如:< ? extends List>)和下限(例如:<? super List>)。
1.3 使用泛型后对象或者集合内只能放入指定的数据类型,可以保证对象或者集合的安全性,减少类型的转换操作。
2.怎么使用泛型,泛型可以作用在什么位置
2.1 有以下几种使用场景以及放在那种位置
泛型只能定义引用数据类型,而不能使用基本数据类型
泛型类、泛型方法、泛型接口、泛型通配符
例如:作用在类上时( public class Animal
作用在对象上时( Animal
作用在方法上时( public
作为方法入参时( public
3.使用泛型的好处
3.1 使用泛型后对象或者集合内只能放入指定的数据类型,避免出现对象或者集合内的对象在多态使用的时候出现类型转换异常(java.lang.ClassCastException),可以保证对象或者集合的安全性。
3.2 指定了类型后,对象、集合或方法内只能使用对应的类型,可以减少类型的转换操作(在没有指定类型是类型转换必须使用 instanceof 关键字来进行判定),缩减了代码了,方便了程序员。
下面以代码的形式讲解
package com.jq;/*** 声明在类上时,写在类名后边* @param <E>*/class Animal <E> {/*** 作为属性声明时,必须在类上声明泛型*/E pet;/*** 作为参数或者返回值时,如果在类上没有声明,必须在访问修饰符和返回值之间* @param pet*/public void setPet(E pet){this.pet = pet;}public E getPet(){return pet;}public <T> void call(T t){System.out.println( t.toString() );}}复制代码
使用泛型实现时,实现类必须使用对应的泛型类。
实现类声明泛型跟接口指定泛型可以同时使用。
package com.jq;/*** 作用在接口上,如果实现该接口时指定实现类型* @param <T>*/public interface Animals<T>{void call(T t);}/*** 拉布拉多犬*//*** 使用泛型实现时,实现类必须使用对应的泛型类。* 实现类声明泛型跟接口指定泛型可以同时使用。*如下代码:*/class LaBuLaDuo<T> implements Animals<String> {public void call(String s) {System.out.println( s );}}
