P498集合-P504List接口-P508ArrayList-p512Vector-P514双向链表-P515LinkedList底层-P518HashSet
P498集合介绍
P499集合的框架体系图
//1. 集合主要是两组(单列集合, 双列集合) //2. Collection 接口有两个重要的子接口List Set , 他们的实现子类都是单列集合 //3. Map 接口的实现子类是双列集合,存放的K-V //4. 把老师梳理的两张图记住(感觉部分类似于Java的字典?)
P500Collection方法
public class Collection1 {
public static void main(String[] args) {
List list1= new ArrayList<>();//(类Arraylist,接口List接收)
//添加单个元素add
list1.add("jack");
list1.add(10);//有自动装箱的过程
list1.add(true);
System.out.println(list1);//输出[jack, 10],此时都是对象
//remove()删除元素
list1.remove(0);//删除第一个元素,返回boolean值
System.out.println(list1);//输出[10]
list1.remove(true);//指定删除某个元素
System.out.println(list1);//输出[10]
//contains:查找元素是否存在
System.out.println(list1.contains(10));//输出true
//size:返回元素的个数
System.out.println(list1.size());//sout1
//isEmpty()是否为空
System.out.println(list1.isEmpty());//soutfalse
//clear:清空
list1.clear();
System.out.println(list1);//sout[]
//添加多个元素addAll
ArrayList List2 = new ArrayList();
List2.add("red");
List2.add("blue");
list1.addAll(List2);
System.out.println(list1);//sout[red, blue]
//contaninsAll:查找多个元素是否都存在
System.out.println(list1.containsAll(List2));//souttrue
//removeAll:删除多个元素
list1.add("yel");
list1.removeAll(List2);
System.out.println(list1);//sout[yel]
}
}
P501Collection接口和常用方法
public class Collection1 {
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 集合
// 1. 先得到col 对应的迭代器
Iterator iterator = col.iterator();
//2. 使用while 循环遍历
/*
while (iterator.hasNext()) {//判断是否还有数据
// //返回下一个元素,类型是Object
Object obj = iterator.next();
System.out.println("obj=" + obj);//动态绑定
//输出obj=Book{name='三国演义', au='罗贯中', price=10.1}
//obj=Book{name='小李飞刀', au='古龙', price=5.1}等
}
*/
//老师教大家一个快捷键,快速生成while => itit
while (iterator.hasNext()) {//直接itit然后回车,或者ctr+J所有快捷模板
Object next = iterator.next();
System.out.println("obj="+next);
}
//3. 当退出while 循环后, 这时iterator 迭代器,指向最后的元素
//iterator.next();//出现NoSuchElementException,因为已经在最后了
// 4. 如果希望再次遍历,需要重置我们的迭代器
iterator = col.iterator();
System.out.println("二次迭代");
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("obj="+next);
}//输出上同
}
}
class Book {
private String name;
private String au;
private double price;
public Book(String name, String au, double price) {
this.name = name;
this.au = au;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAu() {
return au;
}
public void setAu(String au) {
this.au = au;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", au='" + au + '\'' +
", price=" + price +
'}';
}
}
感觉和Python的迭代器类似,next()和数据结构中的堆栈中的指针类似
P502Collection接口遍历对象方式2——for循环的增强
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
for(Object book:col){//可用于集合和数组,这个是在Collection集合中的使用
System.out.println("book="+book);
}//底层依旧是迭代器,快捷方式I
P503
//测试两种方式
public class Collection2 {
public static void main(String[] args) {
List list =new ArrayList();//list接口接收,当然也可以collection
list.add(new Dog("y1",10));
list.add(new Dog("y2",11));
list.add(new Dog("y3",12));
Iterator it= list.iterator();
while (it.hasNext()) {
Object next = it.next();
System.out.println(next);
}
for (Object o :list) {
System.out.println(o);
}
}
}
class Dog{
private String name;
private int age;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
P504list接口
//1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复[案例]
List list = new ArrayList();
list.add("jack");
list.add("tom");
list.add("mary");
list.add("hsp");
System.out.println(list);//输出[jack, tom, mary, hsp]
list.add("tom");
System.out.println(list);//输出[jack, tom, mary, hsp, tom]
//2. List 集合中的每个元素都有其对应的顺序索引,即支持索引
// 索引是从0 开始的
System.out.println(list.get(3));//输出hsp
//1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复[案例]
List list = new ArrayList();
list.add("1jack");
list.add("2tom");
list.add("3mary");
list.add("4hsp");
list.add("5tom");
System.out.println(list);//输出[1jack, 2tom, 3mary, 4hsp,5tom]
//list方法
// void add(int index, Object ele):在index 位置插入ele 元素
//(1) 在index = 1 的位置插入一个对象
list.add(1, "韩顺平");
System.out.println( list);//输出[1jack, 韩顺平, 2tom, 3mary, 4hsp, 5tom]
// 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);//输出[1jack, jack, tom, 韩顺平...
//(2) Object get(int index):获取指定index 位置的元素
// (3)int indexOf(Object obj):返回obj 在集合中首次出现的位置
System.out.println(list.indexOf("tom"));//sout2
// (4)int lastIndexOf(Object obj):返回obj 在当前集合中末次出现的位置
list.add("韩顺平");
System.out.println(list.lastIndexOf("韩顺平"));//输出8
// (5)Object remove(int index):移除指定index 位置的元素,并返回此元素
list.remove(0);
System.out.println(list);//输出[jack, tom, 韩顺平, 2tom, 3mary, 4hsp, 5tom, 韩顺平]
//(6) Object set(int index, Object ele):设置指定index 位置的元素为ele , 相当于是替换.
list.set(1, "玛丽");
System.out.println(list);//sout[jack, 玛丽, 韩顺平...
//(5) List subList(int fromIndex, int toIndex):返回从fromIndex 到toIndex 位置的子集合
// 注意返回的子集合fromIndex <= subList < toIndex
List rlist=list.subList(1,2);//前闭后开
System.out.println(rlist);//sout[玛丽]
P505list练习
List list = new ArrayList();
String s="0123456789";
char [] chars=s.toCharArray();
for (int i = 0; i < s.length(); i++) {
list.add(chars[i]);
}
list.set(1,"hspjy");
System.out.println(list);//sout[0, hspjy, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println(list.get(4));//sout4
System.out.println(list.remove(5));//sout5
System.out.println(list.set(6,"677"));//sout7
System.out.println(list);//sout[0, hspjy, 2, 3, 4, 6, 677, 8, 9]
Iterator ir = list.iterator();
while (ir.hasNext()) {
Object next = ir.next();
System.out.println(next);
}
//就是List list = new LinkedList();
P507list排序练习
//冒泡排序
public class Collection2 {
public static void main(String[] args) {
List list1=new ArrayList();
//可以把ArrayList换成其他两个,在集合中用size表示范围
list1.add(new Book("red1","y1",100));
list1.add(new Book("red2","y2",10));
list1.add(new Book("red3","y3",9));
list1.add(new Book("red4","y4",80));
list1.add(new Book("red2","y2",10));
System.out.println(list1);
// SortTest(list1);
Iterator it= list1.iterator();
while (it.hasNext()) {
Object next = it.next();
System.out.println(next);
}
}
public static void SortTest(List list1){
for (int i = 0; i <list1.size()-1 ; i++) {
for (int j = 0; j < list1.size()-i-1; j++) {
Book book1=(Book) list1.get(j);//取出是对象
Book book2=(Book) list1.get(j+1);
if(book1.getPrice() > book2.getPrice()){
list1.set(j,book2);
list1.set(j+1,book1);
}
}
}
}
}
P508ArrayList注意事项,底层结构和源码
ArrayList alist = new ArrayList();
alist.add(null);
alist.add("lucy");
System.out.println(alist);
//ArrayList线程不安去无synchronized不安全
/*
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
*/
P509ArrayList扩容机制
elementData属性的,object[]数组什么都可以放
2.构造器ArrayList(),ArrayList(int).
//老韩解读源码
// 注意,注意,注意,Idea 默认情况下,Debug 显示的数据是简化后的,如果希望看到完整的数据
// 需要做设置.
// 使用无参构造器创建ArrayList 对象
ArrayList list = new ArrayList();
//ArrayList list = new ArrayList(8);
// 使用for 给list 集合添加1-10 数据
for (int i = 1; i <= 10; i++) {
list.add(i);
}
//使用for 给list 集合添加11-15 数据
for (int i = 11; i <= 15; i++) {
list.add(i);
}
list.add(100);
list.add(200);
list.add(null);
追源码看明白了,注意刚开始的10(可能是版本不一样,我的源码没有刚开始的0+0的初始扩容?)
P512Vector
!
//1.new Victor()底层
/*
public Vector() {
this(10);
}
*/
Vector vector = new Vector();
for (int i = 0; i <10 ; i++) {
vector.add(i);
}
vector.add(100);
/* 2.1 //下面这个方法就添加数据到vector 集合
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
2.2 //确定是否需要扩容条件: minCapacity - elementData.length>0
private void ensureCapacityHelper(int minCapacity) {
overflow-conscious code
if (minCapacity - elementData.length > 0){
grow(minCapacity);
}
2.3 //如果需要的数组大小不够用,就扩容, 扩容的算法
//newCapacity = oldCapacity + ((capacityIncrement > 0) ?
// capacityIncrement : oldCapacity);
//就是扩容两倍.
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
*/
514双向链表模板
!
public class LinkedList {
public static void main(String[] args) {
//模拟一个双向链表
Node node1 = new Node("1y");
Node node2 = new Node("2y");
Node node3 = new Node("3y");
//连接三个节点,实现双向链表
node1.next=node2;
node2.next=node3;
node3.pre=node2;
node2.pre=node1;
Node first=node1;//就是双向链表的头
Node last=node3;//就是双向链表的尾
//演示从头到尾
/*
while(true){
if(first==null){
break;
}
//输出first信息
System.out.println(first);
first=first.next;//输出Node name=1y...
}
//演示从尾到头
while(true){
if(last==null){
break;
}
System.out.println(last);
last=last.pre;//输出Node name=3y...
}
*/
//演示添加和删除对象
//在y2和y3加入y2.5
//1.先创建对象
Node node25 = new Node("y2.5");
node25.next=node3;
node25.pre=node2;
node3.pre=node25;
node2.next=node25;
//让first再指向node1
first=first.next;
last=last.pre;
while(true){
if(first==null){
break;
}
//输出first信息
System.out.println(first);//输出Node name=1y...
first=first.next;
}
}
}
//定义一个node类,Node对象表示一个节点
class Node{
public Object item; //真正存放数据
public Node next; //指向后一个结点
public Node pre; //指向前一个结点
public Node(Object name) {
this.item = name;
}
public String toString() {
return "Node name=" + item;
}
}
P515LinkedList底层结构
package New;
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedListCRUD {
public static void main(String[] args) {
LinkedList l1 = new LinkedList();
l1.add(1);
l1.add(2);
l1.add(3);
System.out.println(l1);
l1.remove();//int 默认删除第一个,输出[2, 3],底层是removeFist(),然后unlinkFirst()
/*默认删除的源码
1.removeFirst()
2.
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
3.
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,此时与下个节点的next联系没有了
first = next;//fist指向下一个
if (next == null)
last = null;
else
next.prev = null;//此时第二个节点pre与第一个断开
size--;
modCount++;
return element;
}
*/
// l1.remove();//object
System.out.println(l1);
/* 源码l1.add(1);
1. LinkedList linkedList = new LinkedList();
public LinkedList() {}
2. 这时linkeList 的属性first = null last = null
3.执行
public boolean add(E e) {
linkLast(e);
return true;
4.将新节点加入双向链表最后,分析linkLast(e);
void linkLast(E e) {
final Node<E> l = last;//l=null,因为lats是空
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;//last指向newNode
if (l == null)
first = newNode;//first指向newNode
else
l.next = newNode;
size++;//此时item=1,last,first=null
modCount++;
}
}
5.l1.add(2);源码
final Node<E> l = last;//此时l=last指向第一个节点不为空
final Node<E> newNode = new Node<>(l, e, null);
//pre指向l,last指向新节点,l指向第一个节点
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;//
size++;
modCount++;
}
*/
//修改某个节点
Object o=l1.set(1,999);
System.out.println(l1);//sout[2, 999]
//获得某个节点
Object o1=l1.get(1);
System.out.println(o1);//sout999
//因为linkedLists实现了list接口
Iterator iterator = l1.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);//sout2 999
}
//或者增强for循环
for (Object o2 :l1) {//大写I
System.out.println(o2);
}
}
}
P516List集合选择
P517set接口和常用方法
//老韩解读
//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);//再次添加null
for(int i = 0; i <10;i ++) {
System.out.println("set=" + set);
}
//遍历
// 方式1: 使用迭代器
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
System.out.println("====fenge");
for (Object o :set) {
System.out.println(o);
}
P518HashSet
public class Set1 {
public static void main(String[] args) {
Set hashset=new HashSet();
/*
//源码
1.
public HashSet() {
map = new HashMap<>();
*/
//2. HashSet 可以存放null ,但是只能有一个null,即元素不能重复
hashset.add(null);
hashset.add(null);
System.out.println("hashSet=" + hashset);//输出hashSet=[null]
//3.
//1. 在执行add 方法后,会返回一个boolean 值
// 2. 如果添加成功,返回true, 否则返回false
// 3. 可以通过remove 指定删除哪个对象
System.out.println(hashset.add("john"));//T
System.out.println(hashset.add("lucy"));//T
System.out.println(hashset.add("john"));//F
System.out.println(hashset.add("jack"));//T
System.out.println(hashset.add("Rose"));//T
hashset.remove("john");
System.out.println("hashset=" + hashset);//4 个,hashset=[null, Rose, lucy, jack]
//4.不能有重复的元素
hashset=new HashSet();
System.out.println(hashset);//输出[]
//4 Hashset 不能添加相同的元素/数据?
hashset.add("lucy");//添加成功
hashset.add("lucy");//加入不了
hashset.add(new Dog("tom"));//OK
hashset.add(new Dog("tom"));//Ok
System.out.println("hashset=" + hashset);
//输出hashset=[Dog{name='tom'}, lucy, Dog{name='tom'}]
//加深
//看源码,做分析, 先给小伙伴留一个坑,以后讲完源码,你就了然
// 去看他的源码,即add 到底发生了什么?=> 底层机制.
hashset.add(new String("hsp"));//ok
hashset.add(new String("hsp"));//加入不了.常量池的同一个对象
//看源码
System.out.println("hashset=" + hashset);
}
}
class Dog{
private String name;
public Dog(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
}