从501开始的
集合实际上就是一个容器,可以来容纳其他类型的数据。
集合可以一次容纳多个对象,在实际开发中,假设要连接数据库,数据库当中有10条记录,要把这10条记录查询出来,这个过程中java程序会将10条数据封装成10个java对象,然后将10个java对象放到某一个集合中,将集合传到前端,然后遍历集合,将一个数据一个数据展现出来。
集合不能直接存储基本数据和java对象,集合中存储的是java对象的内存地址。(或者说集合中存储的是引用)
在java中每一个不同的集合底层会对应不同的结构,往不同的集合中存储元素等于将数据放到了不同的数据结构中。
数据结构就是数据存储的结构,如数组、二叉树、链表、哈希表等。
new ArrayList(); 创建一个集合对象,底层是数组
new LinkedList(); 创建一个集合对象,底层是链表
new TreeSet(); 创建一个集合对象,底层是二叉树
集合在Java.util.*; 所有的集合类和集合接口都在java.util下
java中集合分为两大类:
解释:首先迭代的意思就是遍历,把集合中的数据一个一个取出来。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90FaSSLL-1616397502354)(F:\学习笔记\学习笔记MD\JAVA学习\JAVApicture\集合\image-20210312161838084.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OoTScPM5-1616397502357)(F:\学习笔记\学习笔记MD\JAVA学习\JAVApicture\集合\image-20210312163144575.png)]
ArrayList:底层是数组。放进去的值可以重复。
LinkedList:底层是双向链表。
Vector:底层是数组,线程安全的,效率较低,使用较少。
HashSet:底层是HashMap,放到HashSet集合的元素等同于放到HashMap集合的key部分。
TreeSet:底层是TreeMap,放到TreeSet集合的元素等同于放到TreeMap集合的key部分。
HashMap:底层是哈希表。
Hashtable:底层也是哈希表,线程安全的,效率较低,使用较少。
Properties:是线程安全的,并且key和value只能存储字符串String。
TreeMap:底层是二叉树,TreeMap集合的key可以自动按照大小顺序排序。
List集合存储元素的特点:
有序可重复。
有序:存进去的顺序和取出来的顺序相同,每一个元素都有下标。
可重复:存进去一个1,可以再存进去一个1。
Set集合存储元素的特点:
无序不可重复。
无序:存进去的顺序和取出来的顺序不一定相同,另外每一个元素没有下标。
不可重复:存进去一个1,不能再存储一个1。
SortedSet集合存储元素的特点:
首先是无序不可重复的,但是SortedSet集合中的元素是可排序的。
无序:存进去的顺序和取出来的顺序不一定相同,另外每一个元素没有下标。
不可重复:例如存进去一个1,不能再存储一个1。
可排序:可以按照大小进行排列。
往HashSet集合加数据:实际上是把数据加到Map集合里的key部分了
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
关于java.util.Collection接口中常用的方法
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
/*
关于java.util.Collection接口中常用的方法
1.Collection中能存放的元素:
没有使用“泛型”之前,Collection中可以存储Object的所有子类型。(注意只能存java对象的内存地址)
使用了“泛型”之后,Collection中只能存储某个具体的类型。
2.Collection中的常用方法
boolean add(Object e) 向集合中添加元素
int size() 返回此集合中的元素数。
void clear() 清空集合
boolean contains(Object o) 判断当前集合是否包含元素o包含返回true
boolean remove(Object o) 删除集合中的元素o
boolean isEmpty() 判断集合中元素个数是否为0
Object[] toArray() 调用这个方法可以把集合转换成数组
*/
public class CollectionTest01 {
public static void main(String[] args) {
//创建一个集合对象
//Collection c = new Collection();//接口时抽象的,无法实例化
Collection c = new ArrayList();//多态
//测试Collection接口中的常用方法
c.add(1200);//自动装箱,实际上放进去了一个对象的内存地址。Integer x = new Integer(1200);
c.add(3.14);//自动装箱
c.add(new Object());//这是个对象
c.add(new Student());//对象
c.add(true);//自动装箱
//获取集合中的元素个数
System.out.println("集合中元素个数是:"+c.size());//5
c.clear();
System.out.println("集合中元素个数是:"+c.size());//0
//再向集合中添加元素
c.add("hello");//"hello"对象的内存地址放到了集合中
c.add("world");
//判断集合是否包含hello
boolean flag = c.contains("hello");
System.out.println(flag);//true
boolean flag1 = c.contains("hello world");
System.out.println(flag1);//false
System.out.println("集合中元素个数是:"+c.size());//2
//删除集合中的元素
c.remove("hello");
System.out.println("集合中元素个数是:"+c.size());//1
//判断集合中是否存在元素
System.out.println(c.isEmpty());//非空返回false
c.clear();
System.out.println(c.isEmpty());//清空之之后返回true,表示集合中没有元素了
c.add("abc");
c.add("asd");
c.add(100);
c.add("hewllo");
//转换成数组
Object[] objs = c.toArray();
for (int i = 0; i< objs.length;i++){
//遍历数组
Object o=objs[i];
System.out.println(o.toString());//不写也自动调用toString方法
}
}
}
class Student{
}
输出:
集合中元素个数是:5
集合中元素个数是:0
true
false
集合中元素个数是:2
集合中元素个数是:1
false
true
abc
asd
100
hewllo
迭代器就是用来把集合中的元素取出来的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CiRid4WK-1616397502363)(F:\学习笔记\学习笔记MD\JAVA学习\JAVApicture\集合\image-20210313102314442.png)]
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
集合遍历/迭代专题
*/
public class CollectionTest02 {
public static void main(String[] args) {
//注意:以下讲解的遍历方式/迭代方式,是所有Collection通用的一种方式
//在Map集合中不能用,在所有的Collection以及子类中可以使用
//创建集合对象
Collection c = new ArrayList();//后面的集合无所谓,主要是看前面的Collection接口怎么遍历迭代
//添加元素
c.add("abc");
c.add("def");
c.add(100);
c.add(new Object());
//对集合Collection进行迭代
//第一步:获取集合对象的迭代器对象Iterator
Iterator it = c.iterator();//Collection接口继承了Iterable接口中的iterator对象
//第二步:通过以上获取的迭代对象开始迭代/遍历集合
/*
iterator对象中有几个常用方法:
boolean hasNext() 如果仍有元素可以迭代,则返回true
Object next()返回迭代的下一个元素
*/
// boolean hasNext = it.hasNext();
// System.out.println(hasNext);
// if (hasNext){
// //不管你当初存进去什么,取出来都是object
// Object obj = it.next();
// System.out.println(obj);
// }
// hasNext = it.hasNext();
// System.out.println(hasNext);
// if (hasNext){
// Object obj = it.next();
// System.out.println(obj);
// }
// hasNext = it.hasNext();
// System.out.println(hasNext);
// if (hasNext){
// Object obj = it.next();
// System.out.println(obj);
// }
// hasNext = it.hasNext();
// System.out.println(hasNext);
// if (hasNext){
// Object obj = it.next();
// System.out.println(obj);
// }
// hasNext = it.hasNext();
// System.out.println(hasNext);
// if (hasNext){
// Object obj = it.next();
// System.out.println(obj);
// }
//用循环
while (it.hasNext()){
Object obj = it.next();
System.out.println(obj);
}
}
}
输出:
abc
def
100
java.lang.Object@14ae5a5
测试List集合有序可重复,Set集合无序不可重复
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class CollectionTest03 {
public static void main(String[] args) {
//创建集合对象
Collection c1 = new ArrayList();
//添加元素
c1.add(1);
c1.add(2);
c1.add(1);
c1.add(4);
//迭代集合
Iterator it = c1.iterator();
while (it.hasNext()){
Object obj = it.next();//取出来的时候是Object类型
System.out.println(obj);//在打印的时候会转换成字符串,因为println会调用toString方法
//输出结果有序(放入顺序和取出顺序一致)可重复
}
System.out.println("--------------");
//HashSet集合:无序不可重复
Collection c2 = new HashSet();
c2.add(100);
c2.add(200);
c2.add(300);
c2.add(90);
c2.add(400);
c2.add(50);
c2.add(60);
c2.add(100);//取出来只有一个100
Iterator it2 = c2.iterator();
while (it2.hasNext()){
System.out.println(it2.next());
}
}
}
输出:
1
2
1
4 //这里什么顺序存进去,什么顺序拿出来,并且可以重复
--------------
400
50
100
200
90
300
60 //这里顺序被打乱了,并且不能重复
他在底层调用了equals方法,而equals方法比较的是内容
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
/*
深入研究一下Collection中的contains方法:
boolean contains(Object o)
判断集合中是否包含某个对象o
包含返回true,不包含返回false
*/
public class CollectionTest04 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
String s1 = new String("abc");
c.add(s1);
String s2 = new String("def");
c.add(s2);
//集合中元素个数
System.out.println("元素个数是:"+c.size());
//新建对象String
String x = new String("abc");
//判断c集合中是否包含abc
System.out.println(c.contains(x));//true,这里判断的是内容,底层调用了equals方法
//
}
}
true
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest05 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//创建用户对象
User u1= new User("jack");
User u2= new User("jack");
//加入集合
c.add(u1);
//判断集合中是否包含u2
System.out.println(c.contains(u2));
//这里如果User类没有重写equals方法,会调用公共父类Object,而Object里的equals方法比较
//的是两个对象的地址,所以没有重写之前是false
Integer x = new Integer(1000);
c.add(x);
Integer y = new Integer(1000);
System.out.println(c.contains(y));//重写之后true
}
}
class User{
private String name;
public User(){};
public User(String name){
this.name = name;
}
//重写equals方法
public boolean equals(Object obj) {
if (obj == null ||!(obj instanceof User)) return false;//传进来的对象是空或者不是一个User子类的时候返回false
if (obj == this)return true;//如果对象和这个比较类的内存地址一样返回true
User u =(User)obj;
return u.name.equals(this.name);//如果名字一样表示同一个人
}
}
//结论:存放在集合中的类型,一定要重写equals方法
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest05 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//创建用户对象
User u1= new User("jack");
User u2= new User("jack");
//加入集合
c.add(u1);
//判断集合中是否包含u2
System.out.println(c.contains(u2));
//这里如果User类没有重写equals方法,会调用公共父类Object,而Object里的equals方法比较
//的是两个对象的地址,所以没有重写之前是false
c.remove(u2);
System.out.println(c.size());//你在下面重写了equals所以因为u1和u2的内容一样,
// 删掉u2就等于删掉u1。如果不重写equals他比较的是内存地址,那就删不掉了。
Integer x = new Integer(1000);
c.add(x);
Integer y = new Integer(1000);
System.out.println(c.contains(y));//重写之后true
//创建集合对象
Collection cc = new ArrayList();
String s1 = new String("hello");
//加进去
cc.add(s1);
//创建一个新的字符串对象
String s2 = new String("hello");
//删除s2
cc.remove(s2);
//集合中的元素
System.out.println(cc.size());//结果是0,因为remove也是调用了equals,
}
}
class User{
private String name;
public User(){};
public User(String name){
this.name = name;
}
//重写equals方法
public boolean equals(Object obj) {
if (obj == null ||!(obj instanceof User)) return false;//传进来的对象是空或者不是一个User子类的时候返回false
if (obj == this)return true;//如果对象和这个比较类的内存地址一样返回true
User u =(User)obj;
return u.name.equals(this.name);//如果名字一样表示同一个人
}
}
//结论:存放在集合中的类型,一定要重写equals方法
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
关于集合元素的remove
重点:当集合结构发生改变时,迭代器必须重新获取,如果还是用以前老的迭代器,会出现异常:java.util.ConcurrentModificationException
重点:在迭代集合过程中,不能调用集合对象的remove方法删除元素,会出现java.util.ConcurrentModificationException
*/
public class CollectionTest06 {
public static void main(String[] args) {
//创建集合
/* Collection c = new ArrayList();
//注意:如果在这个地方即没有添加元素之前获取迭代器,他指向的是集合中没有元素状态下的迭代器
//一定要注意:集合结构只要发生改变,迭代器必须重新获取。
//当集合结构发生改变,迭代器没有重新获取时,调用next()方法报错:java.util.ConcurrentModificationException
//Iterator it = c.iterator();
//添加元素
c.add(1);//Integer类型
c.add(2);
c.add(3);
c.add(4);
//获取迭代器
Iterator it = c.iterator();
while (it.hasNext()){
Object obj = it.next();//编写代码时,next()方法返回值必须是Object
System.out.println(obj);//obj就代表集合当中的元素
}*/
Collection c2 = new ArrayList();
c2.add("abc");
c2.add("def");
c2.add("xyz");
Iterator it2 = c2.iterator();
while (it2.hasNext()){
Object o = it2.next();
//删除元素
//删除元素之后,集合的结构发生了变换,应该重新获取迭代器,但是循环下一次的时候没有重新获取迭代器
//会出现java.util.ConcurrentModificationException
//c2.remove(o);//直接通过集合去删除元素,没有通知迭代器(导致迭代器的快照和原集合状态不同)
//使用迭代器来删除
it2.remove();//删除的一定是迭代器指向的当前元素
System.out.println(c2.size());
}
}
}
2
1
0
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
List接口中的常用方法
1.List集合存储元素特点:有序可重复
有序:List集合中的元素有下标。从0开始以1递增。
可重复:存储一个1,还可以再存储1。
2.List方法既然是Collection接口的子接口,那么肯定List接口有自己"特色"的方法:
以下只列出List接口特有的常用方法:
void add(int index, Object element) 在指定下标位置上添加元素,第一个元素是下标,添加之后后面的以此移位
Object get(int index) 返回指定下标的元素
int indexOf(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int lastIndexOf(Object o) 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
Object remove(int index) 删除该列表中指定位置的元素
Object set(int index, Object element) 修改指定下标位置的元素
以后开发可以翻阅文档
*/
public class ListTest01 {
public static void main(String[] args) {
//创建List类型的集合
List myList = new ArrayList();
//添加元素
myList.add("A");
myList.add("B");
myList.add("C");
myList.add("C");
myList.add("D");//默认往集合末尾添加指定元素
myList.add(1,"King");//在指定下标位置上添加元素,效率比较低,不常用
//迭代
Iterator iterator = myList.iterator();
while (iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
System.out.println("--------------------------");
//根据下标获取元素
Object firstObj = myList.get(0);
System.out.println(firstObj);//A
//因为有下标,所以List方法有自己特殊的遍历方式---通过下标遍历【set没有】
for (int i = 0; i < myList.size(); i++) {
Object o = myList.get(i);
System.out.println(o);
}
System.out.println("-----------------");
//获取指定对象第一次出现处的索引。
System.out.println(myList.indexOf("King"));// 1
//获取指定对象最后一次出现处的索引
System.out.println(myList.lastIndexOf("C"));//4
//删除指定下标位置的元素
myList.remove(0);
System.out.println(myList.size());//5
System.out.println("------------------");
//修改指定下标位置的元素
myList.set(2,"Soft");
//遍历集合
for (int i = 0; i < myList.size(); i++) {
Object o = myList.get(i);
System.out.println(o);
}
}
}
输出:
A
King
B
C
C
D
--------------------------
A
A
King
B
C
C
D
-----------------
1
4
5
------------------
King
B
Soft
C
D
ArrayList集合:
数组的优缺点:
补充:>>右移、<<左移运算符,右移一位相当于/2,左移一位相当于*2
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.List;
/*
ArrayList集合:
1.默认初始化容量是10
2.集合底层是一个Object[]数组
3.构造方法:
new ArrayList()
new ArrayList(20)
4.ArrayList集合扩容:
扩容后的容量是原来容量的1.5倍
ArrayList集合底层是数组,要尽可能少的扩容,因为数组扩容效率比较低,建议在使用ArrayList集合的时候
预计估计集合个数,给定初始化容量。
5.数组优缺点:
数组的优点:检索效率比较高。(每个元素占用空间大小相同,内存地址是连续的,知道首元素地址,然后知道
下标,通过数学表达式计算内存地址,所以检索效率最高)
数组缺点:随机增删元素效率比较低。但是向数组末尾添加元素效率还是比较难高的
数组无法存储大数据量,因为很难找到一块大的连续的内存空间
6.面试官问:这么多集合用那个集合比较多:
ArrayList集合,因为往数组末尾添加元素,效率不受影响,另外我们检索\查找某个元素比较多。
*/
public class ArrayListTest01 {
public static void main(String[] args) {
//默认初始化容量是10
//数组的长度是10
List List1 = new ArrayList();
//集合的size方法是获取当前结合中元素的个数
System.out.println(List1.size());//0
//指定初始化容量
//数组长度是20
List List2 = new ArrayList(20);
System.out.println(List2.size());//0
}
}
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/*
集合ArrayList的构造方法
*/
public class ArrayListTest02 {
public static void main(String[] args) {
//初始化容量10
ArrayList myList1 = new ArrayList();
//指定初始化容量100
ArrayList myList2 = new ArrayList(100);
//创建一个HashSet集合
Collection c = new HashSet();
//添加元素到Set集合
c.add(100);
c.add(200);
c.add(300);
//通过这个构造方法就可以将HashSet集合转换成List集合。
List myList3 = new ArrayList(c);
for (int i = 0; i < myList3.size(); i++) {
System.out.println(myList3.get(i));
}
}
}
100
200
300
链表优点:
链表缺点:
链表中的元素,在空间存储上,内存地址不连续。
我们一般添加元素都是往末尾添加,所以ArrayList用的比较多
package com.bjpowernode.javase.danLink;
/*
单链表中的节点
节点是单向链表中的基本单元。
每个节点Node都有两个属性:
一个属性是存储数据
另一个属性是下一个节点的内存地址。
*/
public class Node {
//存储数据
Object data;
//下一个节点的内存地址
Node next;
public Node(){
}
public Node(Object data,Node next){
this.data = data;
this.next = next;
}
}
package com.bjpowernode.javase.danLink;
public class Link {
//头节点
Node header = null;
int size = 0;
public int size(){
return size;
}
//向链表中添加元素(向末尾添加)
public void add(Object data){
//创建一个新的节点对象
//让之前单链表的末尾节点next指向新的节点对象。
//有可能这个元素是第一个,也可能不是第一个。
if (header == null){
//说明还没有节点,就new一个新的节点对象作为头节点对象。
//这时候的头节点既是头节点,又是末尾节点。
header = new Node(data,null);
}else {
//说明头不是空,头节点已经有了
//找出当前末尾节点,让当前末尾节点的next是新的节点
Node currentLastNode = finaLast(header);
currentLastNode.next = new Node(data,null);
}
size++;
}
/**
* 专门查找末尾节点的方法
* @param
* @return
*/
private Node finaLast(Node node) {
if (node.next == null){//如果一个节点的next是null说明这个几点是末尾节点
return node;
}
return finaLast(node.next);//用递归去找
}
//删除链表中某个元素的方法
public void remove(Object obj){
}
}
package com.bjpowernode.javase.danLink;
public class Test {
public static void main(String[] args) {
//创建了一个集合
Link link = new Link();
//往集合中添加元素
link.add(100);
link.add(200);
link.add(300);
link.add(400);
//获取元素个数
System.out.println(link.size);
}
}
输出:4
package com.bjpowernode.javase.collection;
import java.util.LinkedList;
/*
LinkedList没有初始化容量,这个链表中没有任何元素,first和last引用都是null
不管是LinkedList还是ArrayList,以后写代码是面向接口编程
LinkedList list = new ArrayList();代表底层是数组
LinkedList list = new LinkedList();代表底层是双向链表,后面都是用list这个引用来调方法编程。
*/
public class LinkedListTest01 {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
System.out.println(obj);
}
}
}
输出:
a
b
c
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
/*
Vector:
1.底层是一个数组。
2.初始化容量:10
3.Vector:扩容之后是原来容量的2倍
4.ArrayList集合扩容特点:是原来容量的1.5倍
5.Vector中所有的方法都是线程同步的,都是synchronized关键字修饰的,是线程安全的,效率较低。
6.如何把一个线程不安全的ArrayList集合转化成线程安全的?
使用集合工具类:
java.util.Collections
java.util.Collection是集合接口
*/
public class VectorTest {
public static void main(String[] args) {
List vector = new Vector();
vector.add(1);
vector.add(2);
vector.add(3);
vector.add(4);
vector.add(5);
vector.add(6);
vector.add(7);
vector.add(8);
vector.add(9);
vector.add(10);
vector.add(11);
for (int i = 0; i < vector.size(); i++) {
System.out.println(vector.get(i));
}
List mylist = new ArrayList();//非线程安全的
//变成线程安全的
Collections.synchronizedList(mylist);
mylist.add("111");
mylist.add("222");
mylist.add("333");
}
}
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
1.JDK5.0之后推出的新特性:泛型
2.泛型这种机制,只在程序编译阶段起作用,只是给编译器参考的。(运行阶段意义不大)
3.使用泛型的好处:
1.集合中存储的元素类型统一了
2.从集合中取出的元素类型是泛型指定的类型,不需要进行大量的"向下转型"!
4.泛型的缺点:
1.导致集合中存储的元素缺乏多样性
5.实际开发中,集合中元素大多是统一的
*/
public class GenericTese01 {
public static void main(String[] args) {
/* //不使用泛型,分析程序存在的缺点
List mylist = new ArrayList();
//准备对象
Cat c = new Cat();
Bird b = new Bird();
//将对象加到集合里
mylist.add(c);
mylist.add(b);
//遍历集合,取出每个对象让他move
Iterator it = mylist.iterator();
while (it.hasNext()){
Object obj = it.next();
//obj中没有move方法,无法调用,只能向下转型。
if (obj instanceof Animal){
Animal a = (Animal)obj;
a.move();
}
}
*/
//使用JDK5之后的泛型机制
//使用泛型List之后,表示List集合只允许存储Animal类型的数据。
//用泛型来指定集合中存储的数据类型,集合元素的数据类型更加统一
List<Animal> mylist = new ArrayList<Animal>();
//mylist.add("a");报错
Cat cat = new Cat();
Bird bird = new Bird();
mylist.add(cat);
mylist.add(bird);
//获取迭代器
//加入泛型之后表示迭代器迭代得是Animal类型
Iterator<Animal> it = mylist.iterator();
while (it.hasNext()){
//使用泛型之后,每次迭代返回的数据都是Animal类型,这里不需要强制类型转换
Animal a = it.next();//直接可以拿到Animal
a.move();
//调用子类特有方法还是需要转换
if (a instanceof Cat){
Cat c = (Cat)a;//你调用子类特有方法还是得向下转型
c.catchMouse();
}
if (a instanceof Bird){
Bird b = (Bird)a;//你调用子类特有方法还是得向下转型
b.fly();
}
}
}
}
class Animal{
public void move(){
System.out.println("动物在移动");
}
}
class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Bird extends Animal{
public void fly(){
System.out.println("鸟儿在飞翔");
}
}
输出:
动物在移动
猫抓老鼠
动物在移动
鸟儿在飞翔
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
JDK8之后引入了自动类型推断机制。又称为钻石表达式
*/
public class GenericTest02 {
public static void main(String[] args) {
//ArrayList<这里的类型会自动推断>,前提是JDK8之后才允许。
List<Animal> myList = new ArrayList<>();
myList.add(new Animal());
myList.add(new Cat());
myList.add(new Bird());
//遍历
Iterator<Animal> it = myList.iterator();
while (it.hasNext()){
Animal a = it.next();
a.move();
}
List<String> stringList= new ArrayList<>();
stringList.add("abc");
stringList.add("http//baidu.com");
//遍历
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()){
String next = iterator.next();//这个迭代器返回的就是String
System.out.println(next);
}
}
}
输出:
动物在移动
动物在移动
动物在移动
abc
http//baidu.com
package com.bjpowernode.javase.collection;
/*
自定义泛型
<>尖括号中的是一个标识符,随便写
java源代码中经常出现的是,
E是Element单词首字母
T是Type单词首字母
*/
public class GenericTest03<标识符随便写> {
public void doSome(标识符随便写 o){
System.out.println(o);
}
public static void main(String[]args){
//new对象的时候指定了是String
GenericTest03<String> gt = new GenericTest03<>();//真正起作用的是在new对象的时候指定的那个类型
gt.doSome("这里只能是String");
GenericTest03<Integer> gt2 = new GenericTest03<>();
gt2.doSome(100);//这里只能是Integer类型,自动装箱
}
}
输出:
这里只能是String
100
语法:
for(元素类型 变量名:数组或者集合){
代码;
}
package com.bjpowernode.javase.collection;
/*
JDK5.0之后推出了一个新特性:叫做增强for循环,或者叫foreach
*/
public class ForEachTest01 {
public static void main(String[] args) {
//int类型数组
int[] arr = {45,25,36,88,95};
//遍历数组
for (int i = 0; i < arr.length; i++) {//普通for循环
System.out.println(arr[i]);
}
//增强for循环(foreach)
/*for(元素类型 变量名:数组或者集合){
System.out.println(变量名);
}*/
//foreach有个缺点是没有下标,在需要使用下标的循环中不建议使用
System.out.println("====================");
for(int data:arr){
//data就是数组中的元素
System.out.println(data);
}
}
}
输出:
45
25
36
88
95
====================
45
25
36
88
95
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
集合使用foreach
*/
public class ForEachTest02 {
public static void main(String[] args) {
//创建List集合
List<String > stringList = new ArrayList<>();
//添加元素
stringList.add("hello");
stringList.add("world");
stringList.add("kitt");
stringList.add("thanks");
//遍历,使用迭代器方式
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
System.out.println("=================");
//使用下标,只针对有下标的集合
for (int i = 0; i < stringList.size(); i++) {
System.out.println(stringList.get(i));
}
System.out.println("====================");
//使用增强for
for (String s:stringList){//s代表集合中的元素
System.out.println(s);
}
System.out.println("============");
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
for (int i : list) {//i代表集合中的元素
System.out.println(i);
}
}
}
输出:
hello
world
kitt
thanks
=================
hello
world
kitt
thanks
====================
hello
world
kitt
thanks
============
1
2
3
package com.bjpowernode.javase.collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/*
HashSet集合特点:无序不可重复
*/
public class HashSetTest01 {
public static void main(String[] args) {
//演示以下HashSet的特点
Set<String> strs = new HashSet<>();
//添加元素
strs.add("hello");
strs.add("hello1");
strs.add("hello2");
strs.add("hello3");
strs.add("hello1");
//遍历
for(String s : strs){
System.out.println(s);
}
/*
hello1
hello2
hello
hello3
1.存储的顺序和取出来的顺序不同
2.不可重复
3.放到HashSet集合中的元素实际是放到HashMap的Key部分了
*/
}
}
package com.bjpowernode.javase.collection;
import java.util.Set;
import java.util.TreeSet;
/*
TreeSet集合特点:
1.无序不可重复,但是存储的元素可以自动按照大小顺序排序
称为:可排序集合
2.这里的无序是存进去的顺序和取出来的顺序不同,并且没有下标
*/
public class TreeSetTest {
public static void main(String[] args) {
//创建集合对象
Set<String> strs = new TreeSet<>();
//添加元素
strs.add("A");
strs.add("B");
strs.add("C");
strs.add("D");
strs.add("D");
strs.add("M");
strs.add("Z");
strs.add("K");
//遍历
for (String s : strs) {
System.out.println(s);
}
/*
A
B
C
D
K
M
Z
从小到大自动排序
*/
}
}
输出:
A
B
C
D
K
M
Z
Interface Map
package com.bjpowernode.javase.collection;
/*
java.util.Map接口中常用的方法
1.Map和Collection没有继承关系
2.Map集合以Key和Value的方式存储数据:键值对
Key和Value都是引用数据类型。
key和Value都是存储对象的内存地址。
Key起到主导地位,Value是Key的一个附属品
3.Map接口中的常用方法:
V put(K key, V value) 向Map集合中添加键值对
V get(Object key) 通过Key获取Value
void clear() 清空Map集合
boolean containsKey(Object key) 判断Map集合中是否包含某个Key
boolean containsValue(Object value) 判断Map集合中是否包含某个Key
boolean isEmpty() Map集合中的元素个数是否为0
Set keySet() 获取Map集合中所有的Key 他返回是个Set集合,印证了HashSet加数据是放到了Map集合的Key部分
V remove(Object key) 通过Key删除键值对
int size() 返回Map集合中键值对的个数
Collection values() 获取Map集合中所有的Value,返回Collection
Set> entrySet()
将Map集合转换成Set集合
假设现在有一个Map集合,如下图
map1集合对象
---------------------
Key Value
1 zhangsan
2 lisi
3 wangwu
4 zhaoliu
Set set = map1.entrySet();
Set集合对象
1=zhangsan
2=lisi
3=wangwu
4=zhaoliu
【注意】:Map集合通过entrySet()方法转换成的Set集合,Set集合中的元素类型是Map.Entry
Map.Entry和String一样是一种类型的名字,只不过Map.Entry是是Map中的静态内部类
*/
package com.bjpowernode.javase.collection;
import java.util.HashSet;
import java.util.Set;
public class MyClass {
//声明一个静态内部类
private static class InnerClass{
//静态方法
public static void m1(){
System.out.println("静态内部类的m1方法执行");
}
//实例方法(非静态方法)
public void m2(){
System.out.println("静态内部类的实例方法");
}
}
public static void main(String[]args){
//类名MyClass.InnerClass
MyClass.InnerClass.m1();
//创建静态内部类对象
MyClass.InnerClass mi = new MyClass.InnerClass();
mi.m2();
//给一个Set集合
//该Set集合中存储的对象是:MyClass.InnerClass类型
Set<MyClass.InnerClass> set = new HashSet<>();
}
}
package com.bjpowernode.javase.collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class MapTest01 {
public static void main(String[] args) {
//创建Map集合对象
Map<Integer,String> map = new HashMap<>();
//向Map集合中添加键值对
map.put(1,"zhangsan");//自动装箱
map.put(2,"lisi");
map.put(3,"wangwu");
map.put(4,"zhaoliu");
//通过key获取Value
String value = map.get(2);
System.out.println(value);//lisi
//获取键值对的数量
System.out.println(map.size());//4
//通过key删除value
map.remove(2);
System.out.println(map.size());//3
//判断是否包含某个key
//contains方法底层调用的都是equals,自定义的数据类型需要重写equals方法
System.out.println(map.containsKey(4));//true
//判断是否包含某个value
System.out.println(map.containsValue("lisi"));//false
//获取所有的value
Collection<String> values = map.values();
for (String s : values) {
System.out.println(s);
}/* zhangsan
wangwu
zhaoliu*/
//清空键值对
map.clear();
System.out.println(map.size());//0
//判断是否为空
System.out.println(map.isEmpty());//true
}
}
package com.bjpowernode.javase.collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
Map集合的遍历
*/
public class MapTest02 {
public static void main(String[] args) {
//第一种方式:获取所有的key,通过遍历key来遍历value
Map<Integer,String> map = new HashMap<>();
map.put(1,"张三");
map.put(2,"李四");
map.put(3,"王五");
map.put(4,"赵六");
//遍历Map集合
//获取所有的Key,所有的Key是一个set集合
Set<Integer> keys = map.keySet();
//迭代器可以
Iterator<Integer> iterator = keys.iterator();
while (iterator.hasNext()){
//取出其中一个key
Integer key = iterator.next();
//通过key获取value
String value = map.get(key);
System.out.println(key + "=" + value);
}
for (Integer k :keys){
System.out.println(k + "=" + map.get(k));
}
}
}
输出:
1=张三
2=李四
3=王五
4=赵六
=================
1=张三
2=李四
3=王五
4=赵六
package com.bjpowernode.javase.collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
Map集合的遍历
*/
public class MapTest02 {
public static void main(String[] args) {
//第一种方式:获取所有的key,通过遍历key来遍历value
Map<Integer,String> map = new HashMap<>();
map.put(1,"张三");
map.put(2,"李四");
map.put(3,"王五");
map.put(4,"赵六");
//第二种方式:Set> entrySet()
//把Map集合直接全部转换成Set集合
//Set集合中的元素类型是:Map.Entry
Set<Map.Entry<Integer,String>> set = map.entrySet();
//遍历Set集合,每一次取出一个Node
//迭代器
/*
Iterator> it = set.iterator();
while (it.hasNext()){
Map.Entry node = it.next();
Integer key = node.getKey();
String value = node.getValue();
System.out.println(key + "=" +value);
}*/
//foreach
//效率比较高,因为获取key和value都是直接从node对象中获取属性值
for (Map.Entry<Integer,String >node:set){
System.out.println(node.getKey() + "=" + node.getValue());
//这个getKey()和getValue()是Map.Entry这个类的方法
}
}
}
输出:
1=张三
2=李四
3=王五
4=赵六