一、集合的理解和好处
二、集合的框架体系
背下来:
Collection 单列集合
Collection 接口有两个重要的子接口 LIst Set ,他们的实现子类都是单列集合
Map双列集合
Map接口的实现子类是双列集合,存放的K-V
//单列集合
ArrayList arrayList = new ArrayList();
arrayList.add("Jack");
arrayList.add("tom");
//双列集合
HashMap hashMap = new HashMap();
hashMap.put("NO1", "北京");
hashMap.put("NO2", "上海");
三、Collection接口和常用方法
(一)Collection接口实现类的特点
List a = new ArrayList();
//add:添加单个元素
a.add("jack");//自动装箱
a.add(10);//自动装箱 list.add(new Integer(10))
a.add(true);//自动装箱
System.out.println("a=" + a);//a=[jack, 10, true]
//remove:删除指定元素
// (Object o)-->boolean (int index)-->Object
a.remove(1);//指定删除某个元素
a.remove("jack");//指定删除某个元素
System.out.println("a=" + a);//a=[true]
//contains:查找元素是否存在
System.out.println(a.contains(10));//false
//size:获取元素个数
System.out.println(a.size());//1
//isEmpty:判断是否为空
System.out.println(a.isEmpty());//false
//clear:清空,把整个元素集合清空
a.clear();
System.out.println("a=" + a);//a=[]
//addAll:添加多个元素
ArrayList b = new ArrayList();
b.add("红楼梦");
b.add("三国演义");
a.addAll(b);
System.out.println("a=" + a);//a=[红楼梦, 三国演义]
//containsAll:查找多个元素是否都存在
System.out.println(a.containsAll(b));//T
//removeAll:删除多个元素
a.removeAll(b);
System.out.println("a=" + a);//a=[]
a.add("聊斋");//不是list2.add
a.removeAll(b);
System.out.println("a=" + a);//a=[聊斋]
(二)Collection接口遍历元素方式1-使用Iterator(迭代器)
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionIterator {
@SuppressWarnings({"all"})
public static void main(String[] args) {
Collection col = new ArrayList();//向上转型
col.add(new Book("三国演义","罗贯中",10.1));
col.add(new Book("小李飞刀","古龙",5.1));
col.add(new Book("红楼梦","曹雪芹",34.6));
System.out.println("col=" + col);//col=[Book{name='三国演义', author='罗贯中', price=10.1}, Book{name='小李飞刀', author='古龙', price=5.1}, Book{name='红楼梦', author='曹雪芹', price=34.6}]
//遍历col集合
//1.先得到 col 对应的迭代器
Iterator iterator = col.iterator();
//2.使用while循环遍历
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);//obj=Book{name='三国演义', author='罗贯中', price=10.1}
//obj=Book{name='小李飞刀', author='古龙', price=5.1}
//obj=Book{name='红楼梦', author='曹雪芹', price=34.6}
}//可按快捷键快速生成 itit while循环
//ctrl + j 生成快捷模板
//3. 当退出while循环后,这时iterator迭代器,指向最后的元素
//iterator.next();//NoSuchElementException
//4.如果希望再次遍历,需要重置迭代器//游标重置
//第二次遍历
iterator = col.iterator();
while (iterator.hasNext()) {
Object obj1 = iterator.next();
System.out.println("obj1=" + obj1);//obj=Book{name='三国演义', author='罗贯中', price=10.1}
//obj=Book{name='小李飞刀', author='古龙', price=5.1}
//obj=Book{name='红楼梦', author='曹雪芹', price=34.6}
}
}
}
class Book {
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
(三)Collection接口遍历元素方式2-for循环增强
Collection col = new ArrayList();//向上转型
col.add(new Book("三国演义","罗贯中",10.1));
col.add(new Book("小李飞刀","古龙",5.1));
col.add(new Book("红楼梦","曹雪芹",34.6));
//1.使用增强for,在Collection集合
//2.增强的for,底层仍是迭代器
//3.增强for可以理解成就是简化版的迭代器遍历
//4.快捷键 I
for(Object book : col) {
System.out.println("book" + book);//bookBook{name='三国演义', author='罗贯中', price=10.1}
//bookBook{name='小李飞刀', author='古龙', price=5.1}
//bookBook{name='红楼梦', author='曹雪芹', price=34.6}
}
//增强for,也可以直接用在数组使用
int[] nums = {1, 8, 10, 90};
for(int i : nums) {
System.out.println("i="+ i);//i=1 i=8 i=10 i=90
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class CollectionFor {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Dog("小黑狗", 3));
list.add(new Dog("大黄",100));
list.add(new Dog("大壮",8));
for (Object dog :list) {
System.out.println("dog= " + dog);//dog= Dog{name='小黑狗', age=3}
//dog= Dog{name='大黄', age=100}
//dog= Dog{name='大壮', age=8}
}
System.out.println("==== 迭代器 =====");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object dog = iterator.next();
System.out.println("dog= " +dog);//dog= Dog{name='小黑狗', age=3}
//dog= Dog{name='大黄', age=100}
//dog= Dog{name='大壮', age=8}
}
}
}
class Dog {
private String name;
private int 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;
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
四、List接口和常用方法
(一)LIst接口基本介绍
//1.List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复【案例】
List list = new ArrayList();
list.add("jack");
list.add("tom");
list.add("mary");
list.add("hsp");
list.add("tom");
System.out.println("list=" + list);//list=[jack, tom, mary, hsp, tom]
//2.List集合中的每个元素都有其对应的顺序索引,即支持索引
//索引从0开始
System.out.println(list.get(4));//tom
(二)List接口的常用方法
public static void main(String[] args) {
List list= new ArrayList();
list.add("张三丰");
list.add("贾宝玉");
//void add(int index, Objext ele):在index位置插入ele元素
list.add(1, "你好");
System.out.println("list=" + list);//list=[张三丰, 你好, 贾宝玉]
//boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
List list2= new ArrayList();
list2.add("jack");
list2.add("tom");
list.addAll(1,list2);
System.out.println("list=" + list);//list=[张三丰, jack, tom, 你好, 贾宝玉]
//Object get(int index):获取指定index位置的元素
//int indexOf(Object obj):返回obj在集合中首次出现的位置
System.out.println(list.indexOf("tom"));//2
//int lastIndexOf(Object obj):放回obj在当前集合中最后一次出现的位置
list.add("你好");
System.out.println("list=" + list);//list=[张三丰, jack, tom, 你好, 贾宝玉, 你好]
System.out.println(list.lastIndexOf("你好"));//5
//Object remove(int index):移除指点index位置的元素,并且返回此元素
list.remove(5);
System.out.println("list=" + list);//list=[张三丰, jack, tom, 你好, 贾宝玉]
//Object set(int index, Object ele):设置指定index的位置元素为ele,相当于替换
list.set(1,"马克");
System.out.println("list=" + list);//list=[张三丰, 马克, tom, 你好, 贾宝玉]
//List subList(int fromIndex, int toIndex):返回fromIndex到toIndex位置的子集合
List returnlist = list.subList(0, 2); // 0 <= subList < 2
System.out.println("returnlist=" + returnlist);//returnlist=[张三丰, 马克]
}
(三)List接口课堂练习
List list= new ArrayList();
for (int i = 0; i < 12; i++) {
list.add("hello" + i);
}
System.out.println("list=" + list);
list.add(1,"abcde");
System.out.println("list=" + list);
//获取第5个元素
System.out.println("第五个元素=" + list.get(4));//第五个元素=hello3
//删除第六个元素
System.out.println("删除第六个元素");
list.remove(5);
System.out.println("list=" + list);
//修改第七个元素
System.out.println("修改第七个元素");
list.set(6, "三国演义");
System.out.println("list=" + list);
//使用迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
输出结果:
list=[hello0, hello1, hello2, hello3, hello4, hello5, hello6, hello7, hello8, hello9, hello10, hello11]
list=[hello0, abcde, hello1, hello2, hello3, hello4, hello5, hello6, hello7, hello8, hello9, hello10, hello11]
第五个元素=hello3
删除第六个元素
list=[hello0, abcde, hello1, hello2, hello3, hello5, hello6, hello7, hello8, hello9, hello10, hello11]
修改第七个元素
list=[hello0, abcde, hello1, hello2, hello3, hello5, 三国演义, hello7, hello8, hello9, hello10, hello11]
obj=hello0
obj=abcde
obj=hello1
obj=hello2
obj=hello3
obj=hello5
obj=三国演义
obj=hello7
obj=hello8
obj=hello9
obj=hello10
obj=hello11
(四)List的三种遍历方式 [ArrayList, ListedList, Vector]
// List 接口的实现子类 Vetor LinkedList
List list= new ArrayList();
list.add("jack");
list.add("tom");
list.add("鱼香肉丝");
list.add("北京烤鸭");
//遍历
//1.迭代器
System.out.println("====迭代器=====");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println(obj);
}
//2.增强for
System.out.println("====增强for====");
for (Object o :list) {
System.out.println(o);
}
//3.普通for
System.out.println("====普通for====");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
输出结果
迭代器
jack
tom
鱼香肉丝
北京烤鸭
增强for
jack
tom
鱼香肉丝
北京烤鸭
普通for
jack
tom
鱼香肉丝
北京烤鸭
运行类型互换ArrayList, ListedList, Vector也一样
//List list= new ArrayList();
//List list= new Vector();
List list= new LinkedList();
(五)实现类的课堂练习2
import java.util.*;
public class ListMethod {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Book("红楼梦", 100, "曹雪芹"));
list.add(new Book("西游记", 10, "吴承恩"));
list.add(new Book("水浒传", 9, "施耐庵"));
list.add(new Book("三国演义", 80,"罗贯中"));
for (Object o :list) {
System.out.println(o);
}
//冒泡排序
sort(list);
System.out.println("====排序后===");
for (Object o :list) {
System.out.println(o);
}
}
//静态方法
//价格要求是从小到大
public static void sort(List list) {
for (int i =0; i <list.size()-1; i++) {
for(int j = 0; j < list.size()-1-i; j++) {
//取出对象Book
Book book1 = (Book)list.get(j);
Book book2 = (Book)list.get(j + 1);
if(book1.getPrice() > book2.getPrice()) {
list.set(j, book2);
list.set(j + 1, book1);
}
}
}
}
}
class Book {
private String name;
private double price;
private String author;
public Book(String name, double price, String author) {
this.name = name;
this.price = price;
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "名称:" + name + "\t\t" + "价格:" + price + "\t\t" + "作者:" + author;
}
}
输出结果:
名称:红楼梦 价格:100.0 作者:曹雪芹
名称:西游记 价格:10.0 作者:吴承恩
名称:水浒传 价格:9.0 作者:施耐庵
名称:三国演义 价格:80.0 作者:罗贯中
==排序后=
名称:水浒传 价格:9.0 作者:施耐庵
名称:西游记 价格:10.0 作者:吴承恩
名称:三国演义 价格:80.0 作者:罗贯中
名称:红楼梦 价格:100.0 作者:曹雪芹
五、ArrayList底层结构和源码分析
(一)ArrayList的注意事项
//ArrayList 是线程不安全的,可以看源码,没有synchronized
// public boolean add(E e) {
// ensureCapacityInternal(size + 1); // Increments modCount!!
// elementData[size++] = e;
// return true;
// }
ArrayList arrayList = new ArrayList();
arrayList.add(null);
arrayList.add("jack");
arrayList.add(null);
System.out.println(arrayList);
(二)ArrayList的底层操作机制源码分析(重点,难点)
总结:
无参构造器:elementDate初始为0,则往后10->15->22 …1.5倍
指定大小构造器:如果elementDate指定为8,则往后8->12->18…1.5倍
(三)ArrayList的底层操作机制分析案例
六、Vector底层结构和源码剖析
(一)Vector的基本介绍
synchronized:支持线程同步和互斥
集合始终只有一个线程操作,用ArrayList,效率高
集合有好多个线程操作,用Vector,是线程安全的,支持线程同步和互斥
(二)Vector和ArrayList的比较
七、LindedList底层结构
(一)LinkedList的全面说明
(二)LinkedList的底层操作机制
public class LinkedList01 {
public static void main(String[] args) {
Node jack = new Node("jack");
Node tom = new Node("tom");
Node hsp = new Node("老韩");
//连接三个节点,形成双向链表
//jack -> tom -> hsp
jack.next = tom;
tom.next = hsp;
//hsp -> tom -> jack
hsp.pre = tom;
tom.pre = jack;
Node first = jack;//让first引用指向jack,就是双向链表的头结点
Node last = hsp;//让last引用指向hsp,就是双向链表的头结点
//演示,从头到尾进行遍历
System.out.println("====从头到尾遍历=====");
while (true) {
if(first == null) {
break;
}
//输出first 信息
System.out.println(first);
first = first.next;
}
//演示,从尾到头进行遍历
System.out.println("====从尾到头遍历=====");
while (true) {
if(last == null) {
break;
}
//输出last 信息
System.out.println(last);
last = last.pre;
}
//演示链表的添加对象/数据
//在tom 和 老韩中加smith
//1.先创建一个Node节点,name就是smith
Node smith = new Node("smith");
//下面就把smith加入到双线链表
smith.next = hsp;
smith.pre = tom;
hsp.pre = smith;
tom.next = smith;
first = jack;//让first引用指向jack,就是双向链表的头结点
//演示,从头到尾进行遍历
System.out.println("====插入后从头到尾遍历=====");
while (true) {
if(first == null) {
break;
}
//输出first 信息
System.out.println(first);
first = first.next;
}
last = hsp;//让last重新指向最后一个节点
//演示,从尾到头进行遍历
System.out.println("====插入后从尾到头遍历=====");
while (true) {
if(last == null) {
break;
}
//输出last 信息
System.out.println(last);
last = last.pre;
}
}
}
//定义一个Node 类,Node对象,表示双向链表的一个节点
class Node {
public Object item;//真正存放数据
public Node next;//指向后一个节点
public Node pre;//指向前一个节点
public Node(Object name) {
this.item = name;
}
@Override
public String toString() {
return "Node name=" + item;
}
}
输出结果:
====从头到尾遍历=====
Node name=jack
Node name=tom
Node name=老韩
====从尾到头遍历=====
Node name=老韩
Node name=tom
Node name=jack
====插入后从头到尾遍历=====
Node name=jack
Node name=tom
Node name=smith
Node name=老韩
====插入后从尾到头遍历=====
Node name=老韩
Node name=smith
Node name=tom
Node name=jack
(三)LinkedList的增删改查案例
@SuppressWarnings({"all"})
public class LinkedListCRUD {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
System.out.println("linkedList=" + linkedList);//linkedList=[1]
//演示删除
linkedList.remove();//默认删除第一个
System.out.println("linkedList=" + linkedList);//linkedList=[2, 3]
//修改某个节点
linkedList.set(1,666);
System.out.println("linkedList=" + linkedList);//linkedList=[2, 666]
//得到某个节点对象
Object o = linkedList.get(0);
System.out.println("linkedList=" + o);//linkedList=2
//因为LinkedList是实现了List接口,遍历方式
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("next=" + next);//next=2
//next=666
}
//增强for
System.out.println("====增强for=====");
for (Object o1 :linkedList) {
System.out.println("o1=" + o1);
}
System.out.println("=====LinkedList普通for===");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
//增加源码码阅读
//1.LinkedList linkedList = new LinkedList();
/*
* public LinkedList() {}
*
* 2.这是LinkedList的属性first = null last = null
* 3.指向 public boolean add(E e) {
linkLast(e);
return true;
}
*4.将新的节点,加入到双向链表的最后
* void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
* */
/*
* 删除源码分析
* 1 public E remove() {
return removeFirst();
}
* private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
*
*
* */
}
输出结果:
linkedList=[1, 2, 3]
linkedList=[2, 3]
linkedList=[2, 666]
linkedList=2
next=2
next=666
====增强for=====
o1=2
o1=666
=====LinkedList普通for===
2
666
(四)ArrayList和LinkedList比较
八、Set接口和常用方法
(一)Set接口基本介绍
@SuppressWarnings({"all"})
public class SetMethod {
public static void main(String[] args) {
//1.以Set接口的实现类 HashSet 来讲解Set 接口的方法
//2.set接口的实现类的对象(Set接口对象),不能存放重复元素,可以添加null,
//3.set接口对象存放对象无序(即添加的顺序和取出的顺序不一致)
//4.取出的顺序是固定的
Set set = new HashSet();
set.add("john");
set.add("lucy");
set.add("john");//重复
set.add("jack");
set.add("hsp");
set.add("mary");
set.add(null);
set.add(null);//重复
for (int i = 0; i < 10; i++) {
System.out.println("set=" + set);
}
//遍历
//方式1:使用迭代器
System.out.println("====使用迭代器====");
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
//删除
set.remove(null);
//方式2:增强for
System.out.println("====增强for====");
for (Object o :set) {
System.out.println("set=" + set);
}
}
}
输出结果:
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
set=[null, hsp, mary, john, lucy, jack]
====使用迭代器====
obj=null
obj=hsp
obj=mary
obj=john
obj=lucy
obj=jack
====增强for====
set=[hsp, mary, john, lucy, jack]
set=[hsp, mary, john, lucy, jack]
set=[hsp, mary, john, lucy, jack]
set=[hsp, mary, john, lucy, jack]
set=[hsp, mary, john, lucy, jack]
(二)HashSet的全面说明
Set hashSet = new HashSet();
hashSet.add(null);
hashSet.add(null);
System.out.println("hashSet=" + hashSet);//hashSet=[null]
public class HashSet01 {
public static void main(String[] args) {
HashSet set = new HashSet();
//说明
//1.在执行add方法后,会返回一个boolean值
//2.如果添加成功,放回 true,否则返回false
System.out.println(set.add("john"));//T
System.out.println(set.add("lucy"));//T
System.out.println(set.add("john"));//F
System.out.println(set.add("jack"));//T
System.out.println(set.add("Ruse"));//T
//3.可以通过remove删除哪个对象
set.remove("john");
System.out.println("set=" + set);//set=[Ruse, lucy, jack]
//
set = new HashSet();
System.out.println("set=" + set);//set=[]
//4.HashSet 不能存放相同元素或数据
set.add("lucy");
set.add("lucy");//加入不了
set.add(new Dog("tom"));
set.add(new Dog("tom"));//new 地址不一样可以加入成功
System.out.println("set=" + set);//set=[name=tom, name=tom, lucy]
//在加深一下,非常经典面试题
set.add(new String("hsp"));//加进去
set.add(new String("hsp"));//加入不了
System.out.println("set=" + set);//set=[hsp, name=tom, name=tom, lucy]
}
}
class Dog {
private String name;
public Dog(String name) {
this.name = name;
}
@Override
public String toString() {
return "name=" + name;
}
}
这里留个坑
(三)HashSet底层机制说明
@SuppressWarnings({"all"})
public class HashSetStructure {
public static void main(String[] args) {
//模拟一个HashMap底层结构 (HashSet 的底层是HashMap)
//1.创建一个数组,数组的类型是Node[]
//2.有些人直接把Node[] 数组称为表
Node[] table = new Node[16];
System.out.println("table=" + table);
//3.创建节点
Node john = new Node("john", null);
table[2] = john;
Node jack = new Node("jack", null);
john.next = jack;//将jack节点挂载到john
Node rose = new Node("Rose", null);
jack.next = rose;//将rose节点挂载到jack后
Node lucy = new Node("lucy", null);
table[3] = lucy;
System.out.println("table=" + table);
System.out.println("table=" + table);
}
}
class Node { //节点,存储数据,可以指向下一个节点
Object item;//存放数据
Node next;//指向下一个节点
public Node(Object item, Node next) {
this.item = item;
this.next = next;
}
}
分析源码卡住
分析HashSet的添加元素底层时候如何实现==(hash() + equals())==
1.先获取元素的哈希值(hashCode方法)。
2.对哈希值进行运算,得到一个索引值极为要存放在哈希表中的位置号。
3.如果该位置上没有其他元素,则直接存放。
4.如果该位置上已经有其他元素,则需要进行equals判断,如果相等,则不再添加,,如果不等,则以链表的方式添加。
(四)HashSet课堂练习1
@SuppressWarnings({"all"})
public class HashSetExercise {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
hashSet.add(new Employee("milan", 18));
hashSet.add(new Employee("smith", 28));
hashSet.add(new Employee("milan", 18));
System.out.println("hashSet=" + hashSet);
}
}
//创建Employee
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.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;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//如果name和age值相同,则返回相同的hash值
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return age == employee.age &&
Objects.equals(name, employee.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
输出结果:
hashSet=[Employee{name='smith', age=28}, Employee{name='milan', age=18}]
(五)HashSet课堂练习2
(六)LInkedHashSet的全面说明
添加元素是有序的
@SuppressWarnings({"all"})
public class LinkedHashSetSource {
public static void main(String[] args) {
Set set = new LinkedHashSet();
set.add(new String("AA"));
set.add(456);
set.add(456);
set.add(new Customer("刘", 1001));
set.add(123);
set.add("HSP");
System.out.println("set=" + set);//set=[AA, 456, com.hspedu.set_.Customer@1b6d3586, 123, HSP]
//1.LInkedHashSet 加入顺序和取出顺序一致
//2.LinkedHashSet底层维护的是一个LInkedHashMap(是HashMap子类)
//3.LinkedHashSet 底层结构(数组table+双向链表)
//4.添加第一次时,直接将 数组table 扩容到16,存放的节点类型是
//5.数组是 HashMap$Node[] 存放的元素/数据是LinkedHashMap$Entry类型
}
}
class Customer {
private String name;
private int no;
public Customer(String name, int no) {
this.name = name;
public static void main(String[] args) {
LinkedHashSet linkedHashSet = new LinkedHashSet();
linkedHashSet.add(new Car(“奥拓”, 1000));
linkedHashSet.add(new Car(“奥迪”, 300000));
linkedHashSet.add(new Car(“法拉利”, 10000000));
linkedHashSet.add(new Car(“奥迪”, 300000));
linkedHashSet.add(new Car(“保时捷”, 70000000));
linkedHashSet.add(new Car(“奥迪”, 300000));
//没重写
// System.out.println(“linkedHashSet=” + linkedHashSet);//都可以
//linkedHashSet=[
//Car{name=‘奥拓’, price=1000.0},
//Car{name=‘奥迪’, price=300000.0},
//Car{name=‘法拉利’, price=1.0E7},
//Car{name=‘奥迪’, price=300000.0},
//Car{name=‘保时捷’, price=7.0E7},
//Car{name=‘奥迪’, price=300000.0}]
//重写equals
System.out.println("linkedHashSet=" + linkedHashSet);
//linkedHashSet=[
//Car{name='奥拓', price=1000.0},
//Car{name='奥迪', price=300000.0},
//Car{name='法拉利', price=1.0E7},
//Car{name='保时捷', price=7.0E7}]
}
}
class Car {
private String name;
private double price;
public Car(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "\nCar{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
//重写equals 和hashCode方法
//当name 和 peice 相同时,返回hashCode值,equals放回t
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return Double.compare(car.price, price) == 0 &&
Objects.equals(name, car.name);
}
@Override
public int hashCode() {
return Objects.hash(name, price);
}
}
九、Map接口和常用方法
(一)Map接口实现类的特点
{
//接口实现类的特点,使用实现类HashMap实现
//1.Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)
//2.Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
//3.Map中的key不允许重复,原因和HashSet一样
//4.Map中的value可以重复
//5.Map中的key可以为 null,value也可以为null,注意key为null只能一次,value可以多次null
//6.常用String类作为Map的key
//7.key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
Map map = new HashMap();
map.put("no1", "韩顺平");//k-v
map.put("no2", "张无忌");//k-v//无序map={no2=张无忌, no1=韩顺平}
map.put("no1", "张三丰");//key-value//当有相同的key,就等价于替换// map={no2=张无忌, no1=张三丰}
map.put("no3", "张三丰");//map={no2=张无忌, no1=张三丰, no3=张三丰}
map.put(null, null);//k-v//map={no2=张无忌, null=null, no1=张三丰, no3=张三丰}
map.put(null,"abc");//等价替换//map={no2=张无忌, null=abc, no1=张三丰, no3=张三丰}
map.put("no4",null);
map.put("no5",null);//map={no2=张无忌, null=abc, no1=张三丰, no4=null, no3=张三丰, no5=null}
map.put(1, "赵敏");//map={no2=张无忌, null=abc, no1=张三丰, 1=赵敏, no4=null, no3=张三丰, no5=null}
map.put(new Object(), "金毛狮王");//map={no2=张无忌, null=abc, no1=张三丰, 1=赵敏, no4=null, no3=张三丰, no5=null, java.lang.Object@1b6d3586=金毛狮王}
System.out.println(map.get("no1"));//张三丰
System.out.println("map=" + map);
}
(二)Map接口的特点
(三)Map接口的常用方法
@SuppressWarnings({"all"})
public class MapMethod {
public static void main(String[] args) {
//演示map接口常用方法
Map map = new HashMap();
map.put("邓超", new Book("", 100));
map.put("邓超", "孙俪");
map.put("王宝强", "马蓉");
map.put("宋吉", "马蓉");
map.put("刘玲播", null);
map.put(null, "刘亦菲");
map.put("鹿晗","关晓彤");
System.out.println("map=" + map);//map={邓超=孙俪, null=刘亦菲, 刘玲播=null, 王宝强=马蓉, 宋吉=马蓉, 鹿晗=关晓彤}
//remove:根据键删除映射关系
map.remove(null);
System.out.println("map=" + map);//map={邓超=孙俪, 刘玲播=null, 王宝强=马蓉, 宋吉=马蓉, 鹿晗=关晓彤}
//get:根据键获取值
map.get("鹿晗");
Object val = map.get("鹿晗");
System.out.println("val=" + val);//val=关晓彤
//size:获取元素个数
System.out.println("k-v=" + map.size());//k-v=5
//isEmpty:判断个数是否为0
System.out.println(map.isEmpty());//false
//clear:清空
map.clear();
System.out.println("map=" + map);//map={}
//containsKey:查找键是否存在
System.out.println(map.containsKey("hsp"));//false
}
}
class Book {
private String name;
private int num;
public Book(String name, int num) {
this.name = name;
this.num = num;
}
(四)Map接口遍历方法
@SuppressWarnings({"all"})
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("邓超", "孙俪");
map.put("王宝强", "马蓉");
map.put("宋吉", "马蓉");
map.put("刘玲播", null);
map.put(null, "刘亦菲");
map.put("鹿晗","关晓彤");
//第一组:先取出所有的Key,通过Key取出对应的Value
Set keySet = map.keySet();
//1.(1)增强for
System.out.println("=====1.(1)增强for=====");
for (Object key :keySet) {
System.out.println(key + "-" + map.get(key));
}
//1.(2)通过迭代器
System.out.println("=====1.(2)通过迭代器=====");
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
//第二组:把所有的values取出
Collection values = map.values();
//这里可以使用所有的Collections使用的遍历方法
//2.(1)增强for
System.out.println("====2.(1)增强for 取出所有的values=====");
for (Object value :values) {
System.out.println(value);
}
//2.(2)迭代器
System.out.println("=====2.(2)通过迭代器 取出所有的values======");
Iterator iterator1 = values.iterator();
while (iterator1.hasNext()) {
Object value = iterator1.next();
System.out.println(value);
}
//第三组:通过EntrySet来获取 k-v
Set entrySet = map.entrySet();// EntrySet<Map.Entry<K.V>>
//(1)增强for
System.out.println("===3.(1)使用EntrySet=== 增强for");
for (Object entry :entrySet) {
//将entry 转成 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
//(2)迭代器
System.out.println("=====3.(2)通过迭代器===entrySet==");
Iterator iterator2 = entrySet.iterator();
while (iterator2.hasNext()) {
Object entry = iterator2.next();
//System.out.println(next.getClass());//HashMap$Node --实现--> Map.Entry(getKey,getValue)
//向下转型 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
}
}
输出结果:
=====1.(1)增强for=====
邓超-孙俪
null-刘亦菲
刘玲播-null
王宝强-马蓉
宋吉-马蓉
鹿晗-关晓彤
=====1.(2)通过迭代器=====
邓超-孙俪
null-刘亦菲
刘玲播-null
王宝强-马蓉
宋吉-马蓉
鹿晗-关晓彤
====2.(1)增强for 取出所有的values=====
孙俪
刘亦菲
null
马蓉
马蓉
关晓彤
=====2.(2)通过迭代器 取出所有的values======
孙俪
刘亦菲
null
马蓉
马蓉
关晓彤
===3.(1)使用EntrySet=== 增强for
邓超-孙俪
null-刘亦菲
刘玲播-null
王宝强-马蓉
宋吉-马蓉
鹿晗-关晓彤
=====3.(2)通过迭代器===entrySet==
邓超-孙俪
null-刘亦菲
刘玲播-null
王宝强-马蓉
宋吉-马蓉
鹿晗-关晓彤
(五)Map接口课堂练习
@SuppressWarnings({"all"})
public class MapExercise {
public static void main(String[] args) {
Map hashMap = new HashMap();
hashMap.put(1, new Emp("jack", 300000,1));
hashMap.put(2, new Emp("tom", 210000,2));
hashMap.put(3, new Emp("milan", 120000,3));
//两种遍历方式
//1. 使用keySet -> 增强for
Set keySet = hashMap.keySet();
System.out.println("===1. 使用keySet -> 增强for==");
for (Object key :keySet) {
//先获取value
Emp emp =(Emp) hashMap.get(key);
if(emp.getSal() > 180000) {
System.out.println(emp);
}
}
//2.使用EntrySet ->迭代器
Set entrySet = HashMap.entrySet();
System.out.println("====//2.使用EntrySet ->迭代器=====");
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
//通过entry取得key和value
Emp emp = (Emp)entry.getValue();
if(emp.getSal() > 18000) {
System.out.println(emp);
}
}
}
}
class Emp {
private String name;
private double sal;
private int id;
public Emp(String name, double sal, int id) {
this.name = name;
this.sal = sal;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", sal=" + sal +
", id=" + id +
'}';
}
}
(六)HashMap小结
(七)HashMap底层机制及源码剖析
(八) HashTable的基本介绍
(九)Map接口实现类-Properties
Properties properties = new Properties();
properties.put("john", 100);//k-v
// properties.put(null, 100);//k-v 不能为空,继承了HashTable//NullPointerException
// properties.put("john", null);//k-v 不能为空,继承了HashTable
properties.put("lucy", 100);
properties.put("lic", 100);
properties.put("lic", 88);//替换
System.out.println("properties=" + properties);//properties={john=100, lic=88, lucy=100}
(十)总结-开发中如何选择集合现实类(记住)
TressMap:
//1.调用无参构造器,排序是无序的
//TreeSet treeSet = new TreeSet();//treeSet=[a, jack, sp, tom]
//2.按照字母大小排
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//按照字母先后排序
return ((String) o1).compareTo((String) o2);//treeSet=[a, jack, sp, tom]
//按照字母长度排序
//return ((String) o1).length() - ((String) o2).length();//treeSet=[a, sp, tom, jack]
}
});
treeSet.add("jack");
treeSet.add("tom");
treeSet.add("sp");
treeSet.add("a");
//treeSet.add("a");//算字母排序,再加入一个相同的值,底层源码进不去,不是替换
treeSet.add("abc");//算长度,加不进去,长度和"tom"长度一样
System.out.println("treeSet=" + treeSet);
TreeMap:
//使用默认构造器
//TreeMap treeMap = new TreeMap();//无序//treeMap={jack=杰克, kristina=可牛斯提诺, smith=史密斯, tom=汤姆}
TreeMap treeMap = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//按照k 字母先后排序
return ((String) o1).compareTo((String) o2);//treeMap={jack=杰克, kristina=可牛斯提诺, smith=史密斯, tom=汤姆}
//按照k 长度排序
//return ((String) o1).length() - ((String) o2).length();//treeMap={tom=汤姆, jack=杰克, smith=史密斯, kristina=可牛斯提诺}
}
});
treeMap.put("jack", "杰克");//k-v
treeMap.put("tom", "汤姆");
treeMap.put("kristina", "可牛斯提诺");
treeMap.put("smith", "史密斯");
treeMap.put("hsp","韩顺平");//按照长度,加入不了,不是替换,是换了value值//treeMap={tom=韩顺平, jack=杰克, smith=史密斯, kristina=可牛斯提诺}
//按照字母,可以进去
System.out.println("treeMap=" + treeMap);
(十一)Collection工具类
//创建ArrayList 集合,用于测试
List list = new ArrayList();
list.add("tom");
list.add("smith");
list.add("king");
list.add("milan");
//reverse(List): 反转 List中的元素
Collections.reverse(list);//list=[milan, king, smith, tom]
//shuffle(List): 对List集合元素进行随机排序
Collections.shuffle(list);//list=[smith, king, milan, tom]
//sort(List):根据字母从小到大排序
Collections.sort(list);
//sort:按照字符串长度排序
Collections.sort(list, new Comparator() {//list=[tom, king, milan, smith]
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).length() - ((String) o2).length();
}
});
//swap(list, int, int) 交换排序
Collections.swap(list, 0, 1);//list=[king, tom, milan, smith]
System.out.println("list=" + list);
//创建ArrayList 集合,用于测试
List list = new ArrayList();
list.add("tom");
list.add("smith");
list.add("king");
list.add("milan");
//reverse(List): 反转 List中的元素
Collections.reverse(list);//list=[milan, king, smith, tom]
//shuffle(List): 对List集合元素进行随机排序
Collections.shuffle(list);//list=[smith, king, milan, tom]
//sort(List):根据字母从小到大排序
Collections.sort(list);
//sort:按照字符串长度排序
Collections.sort(list, new Comparator() {//list=[tom, king, milan, smith]
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).length() - ((String) o2).length();
}
});
//swap(list, int, int) 交换排序
Collections.swap(list, 0, 1);//list=[king, tom, milan, smith]
//Object max(Collection):根据元素的自然顺序,字母开头最大,返回给定的集合中的最大元素
//System.out.println("自然顺序最大元素=" + Collections.max(list));
//System.out.println("list=" + list);
//Object max(COllection,Comparator):根据 Comparator指定的顺序,返回给定集合中的最大元素
//比如,我们要返回长度最大的元素
Object maxObject = Collections.max(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).length() - ((String) o2).length();
}
});
System.out.println("最大长度元素=" + maxObject);//最大长度元素=milan
//int frequency(Collection, Object):返回指定集合中的指定元素的出现次数
System.out.println("tom出现的次数=" + Collections.frequency(list, "tom"));//tom出现的次数=1
//void copy(List dest, List src):将src 中的内容复制到dest中
ArrayList dest = new ArrayList();
//为了完成一个完整的拷贝,我们需要给dest赋值,大小和list.size()一样
for (int i = 0; i < list.size(); i++) {
dest.add("");
}
Collections.copy(dest, list);
System.out.println("dest=" + dest);//dest=[king, tom, milan, smith]
//boolean replaceArr(List list, Object oldVal, Object newVal):使用新值替换List对象的所有旧值
Collections.replaceAll(list, "tom" ,"汤姆");
System.out.println("list=" + list);//list=[king, 汤姆, milan, smith]
(十)集合家庭作业
public class Properties_ {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new news("新冠确诊病例超千万,数百万印度教教信徒赴恒河”圣浴“引民众担忧"));
arrayList.add(new news("男子突然想起2个月前钓的鱼还在网兜里,捞起一看赶紧放生"));
int size = arrayList.size();
for (int i =size - 1; i >= 0; i--) {
news news =(news) arrayList.get(i);
System.out.println(processTitle(news.getTitle()));
}
}
//专门写个标题,处理实现新闻标题
public static String processTitle(String title) {
if(title == null) {
return "";
}
if(title.length() > 15) {
return title.substring(0, 15) + "...";//[0, 15)
} else {
return title;
}
}
}
class news {
private String title;
private String contents;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
public news(String title) {
this.title = title;
}
@Override
public String toString() {
return "title=" + title;
}
}
输出结果:
男子突然想起2个月前钓的鱼还在...
新冠确诊病例超千万,数百万印度...
@SuppressWarnings({"all"})
public class Properties_ {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
Car car = new Car("宝马", 400000);
Car car1 = new Car("宾利", 5000000);
//1.add:添加单个元素
arrayList.add(car);
arrayList.add(car1);
//System.out.println(arrayList);//[Car{name='宝马', price=400000.0}, Car{name='宾利', price=5000000.0}]
//2.remove
arrayList.remove(car);
//System.out.println(arrayList);//[Car{name='宾利', price=5000000.0}]
//3.contains:查找是否存在
//System.out.println(arrayList.contains(car));//false
//4.size:大小
System.out.println(arrayList.size());//1
//5.isEmpty 判断是否为空
System.out.println(arrayList.isEmpty());//false
//6.clear 清空
//7.addAll:添加多个元素
arrayList.addAll(arrayList);
System.out.println(arrayList);//[Car{name='宾利', price=5000000.0}, Car{name='宾利', price=5000000.0}]
//8.contaidAll
arrayList.containsAll(arrayList);
//9.removeAll
}
}
class Car {
private String name;
private double price;
public Car(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
Map m = new HashMap();
m.put("jack", 650);//int->Integer
m.put("tom", 1200);
m.put("smith", 2900);
//System.out.println(m);//{tom=1200, smith=2900, jack=650}
m.put("jack", 2600);//替换
//System.out.println(m);//{tom=1200, smith=2900, jack=2600}
//为所有员工加薪100元
//keySet
Set keySet = m.keySet();
for(Object obj:keySet) {
m.put(obj, (Integer)m.get(obj) + 100);
}System.out.println(m);//{tom=1300, smith=3000, jack=2700}
//遍历
System.out.println("====遍历====");
Set entrySet = m.entrySet();
//迭代器
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry)iterator.next();
System.out.println(entry.getKey() + "-" + entry.getValue());
}
System.out.println("==遍历所有的工资==");
Collection values = m.values();
for (Object value :values) {
System.out.println(value);
}
{tom=1300, smith=3000, jack=2700}
====遍历====
tom-1300
smith-3000
jack-2700
==遍历所有的工资==
1300
3000
2700