容器的概念
java容器是javaAPI所提供的一系列类的实例,用于在程序中存放对象,主要位于Java.util包中,其长度不受限制,类型不受限制,在存放String类的时候依然能够存放Integer类,两者不会冲突。
容器 API
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。——百度百科
Collection 接口
Collection 接口存储一组不唯一,无序的对象
List 接口
List 接口存储一组不唯一,有序(插入顺序)的对象
- List接口的实现类LinkedList
Set 接口
Set 接口存储一组唯一,无序的对象
(存入和取出的顺序不一定一致)
操作数据的方法与List类似,Set接口不存在get()方法
- Set接口中的实现类
- HashSet:采用Hashtable哈希表存储结构
–优点:添加速度快,查询速度快,删除速度快
–缺点:无序
–LinkedHashSet
采用哈希表存储结构,同时使用链表维护次序
有序(添加顺序) - HashSet是通过元素的两个方法,hashCode和equals方法来完成来保证元素的唯一性的。如果元素的HashCode值相同,才会判断equals是否为true;如果元素的hashCode值不同,不会调用equals方法
- TreeSet
–采用二叉树(红黑树)的存储结构
–优点:有序(排序后的升序)查询速度比List快
–缺点:查询速度没有HashSet快
- HashSet:采用Hashtable哈希表存储结构
Iterator 接口
所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象。
Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作。
Iterator接口定义了如下方法:
boolean hasNext(); //判断是否有元素没有被遍历
Object next(); //返回游标当前位置的元素并将游标移动到下一个位置
void remove();//删除游标左面的元素,在执行完next之后该操作只能执行一次
1.所有的集合类均未提供相应的遍历方法,而是把遍历交给迭代器完成。迭代器为集合而生,专门实现集合遍历
2.Iterator是迭代器设计模式的具体实现
3.可以使用Iterator遍历的本质是实现Iterable接口
- For-each循环
- 增强的for循环,遍历array或Collection的时候相当简便 –无需获得集合和数组的长度,无需使用索引访问元素,无需循环条件
- 遍历集合时底层调用Iterator完成操作
- For-each缺陷
- 数组:
不能方便的访问下标值
不要在for-each中尝试对变量赋值,只是一个临时变量 - 集合:与使用Iterator相比,不能方便的删除集合中的内容
- 数组:
- For-each总结
除了简单的遍历并读出其中的内容外,不建议使用增强for
Collections工具类
Collections和Collection不同,前者是集合的操作类,后者是集合接口
- Collections提供的静态方法
addAll():批量添加
sort():排序
binarySearch():二分查找
fill():替换
shuffle():随机排序
reverse():逆序
Comparable 接口
所有可以“排序”的类都实现了java.lang.Comparable 接口, Comparable接口中只有一个方法
public int compareTo(Object obj);
/*
this == obj 返回0
this > obj 返回正数
this < obj 返回负数
*/
sort排序
泛型
解决数据类型操作不统一产生的异常
使用泛型可以更好的去保护数据类型
- 泛型类的定义
......
public class Notepad<K,V> {// 此处指定了两个泛型 private K key;//此变量的类型由外部决定
private V value;//此变量的类型由外部决定
......
}
......
Notepad<String,Integer>t=null;//指定两个泛型类型的对象
//Key为String,Value为Integer
t=new Notepad<String,Integer>();
t.setKey("张三");
t.setValue(30);
System.out.println("姓名:"+t.getKey()+"\t年龄:"+t.getValue());
Map 接口
Map接口存储一组键值对象,提供key到value的映射
- Map
– 特点key-value映射 - HashMap
– Key无序 唯一(Set)
– Value无序 不唯一(Collection) - LinkedHashMap
– 有序的HashMap 速度快 - TreeMap
– 有序 速度没有hash快 - 问题:Set与Map有关系吗?
– 采用了相同的数据结构,只用于map的key存储数据,以上是Set
集合总结
面试题
-
集合与数组的比较
-
Collection和Collections的区别
-
ArrayList和LinkedList的联系和区别
-
Vector和ArrayList的联系和区别
-
HashMap和Hashtable的联系和区别
Collection 接口
package com.petrel;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author Petrel
* @data 2020/6/22 16:38
*/
/**
* java集合框架:
* Collection:存放的是单一值
* 特点:
* 1、可以存放不同类型的数据,而数组只能存放固定类型的数据
* 2、当使用arraylist子类实现的时候,初始化的长度是10,当长度不够的时候会自动进行扩容操作(1.5倍扩容)
* api方法:
* 增加数据的方法
* add:要求必须传入的参数是Object对象,因此当写入基本数据类型的时候,包含了自动拆箱和自动装箱的过程
* addAll:添加另一个集合的元素到此集合中
*
* 删除数据的方法
* clear:只是清空集合中的元素,但是此集合对象并没有被回收
* remove:删除指定元素
* removeAll:删除集合元素
*
* 查询数据的方法
* contains:判断集合中是否包含指定的元素值
* containsAll:判断此集合中是否包含另一个集合
* isEmpty:判断集合是否等于空
* retainAll:若集合中拥有另一个集合的所有元素,返回true,否则返回false
* size:返回当前集合的大小
*
* 目前没有修改的逻辑
*
* 集合转数组的操作
* toArray:将集合转换成数组
*
*/
public class CollectionDemo {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(1); //1自动装箱成了new Integer(1)
collection.add(true);
collection.add(1.23);
collection.add("abc");
System.out.println(collection);//运行结果:[1, true, 1.23, abc]
((ArrayList) collection).add(0,"petrel");//((ArrayList) collection)强制类型转换
System.out.println(collection);//运行结果:[petrel, 1, true, 1.23, abc]
Collection collection1 = new ArrayList();
collection1.add("a");
collection1.add("b");
collection1.add("c");
collection1.add("d");
collection.addAll(collection1);//addAll添加另一个集合的元素到此集合中 就是添加collection1到原来的collection中
System.out.println(collection);//运行结果:[petrel, 1, true, 1.23, abc, a, b, c, d]
// collection.clear();//清空了集合中的元素,但是集合对象没有被回收
// System.out.println(collection);//运行结果:[]
System.out.println(collection.contains("a"));//判断集合中是否包含指定的元素值,如果将clear()注释,运行结果为true,如果不注释,运行结果为false
System.out.println(collection.containsAll(collection1));//判断此集合中是否包含另一个集合,如果将clear()注释,运行结果为true,如果不注释,运行结果为false
System.out.println(collection.isEmpty());//判断集合是否等于空
collection.remove("a");//删除指定元素 删除collection中的a
System.out.println(collection);//运行结果:[petrel, 1, true, 1.23, abc, b, c, d]
// collection.removeAll(collection);//删除集合元素
// System.out.println(collection);//运行结果:[]
//retainAll:若集合中拥有另一个集合的所有元素,返回true,否则返回false
System.out.println(collection.containsAll(collection1));//运行结果:false
System.out.println(collection1.containsAll(collection));//运行结果:true
//collection.toArray().var; 自动补全
Object[] objects = collection.toArray();//toArray:将集合转换成数组
collection.add("b");
System.out.println(collection);//运行结果:[petrel, 1, true, 1.23, abc, b, c, d, b]
}
}
List 接口
package com.petrel;
/**
* @author Petrel
* @data 2020/6/22 17:45
*/
import java.util.ArrayList;
import java.util.List;
/**
* java集合框架:
* List:存放的是单一值
* List 接口存储一组不唯一,有序(插入顺序)的对象。
* 特点:
* 1、可以存放不同类型的数据,而数组只能存放固定类型的数据
* 2、当使用arraylist子类实现的时候,初始化的长度是10,当长度不够的时候会自动进行扩容操作
* api方法:
* 增加数据的方法
* add:要求必须传入的参数是Object对象,因此当写入基本数据类型的时候,包含了自动拆箱和自动装箱的过程
* addAll:添加另一个集合的元素到此集合中
*
* 删除数据的方法
* clear:只是清空集合中的元素,但是此集合对象并没有被回收
* remove:删除指定元素
* removeAll:删除集合元素
*
* 查询数据的方法
* contains:判断集合中是否包含指定的元素值
* containsAll:判断此集合中是否包含另一个集合
* isEmpty:判断集合是否等于空
* retainAll:若集合中拥有另一个集合的所有元素,返回true,否则返回false
* size:返回当前集合的大小
*
* //集合转数组的操作
* toArray:将集合转换成数组
*/
public class ListDemo {
public static void main(String[] args) {
List list = new ArrayList();
list.add("a");
list.add(1);
list.add("a");
list.add(true);
System.out.println(list);//运行结果:[a, 1, a, true]
//返回list中 号位置的值
System.out.println(list.get(1));//运行结果:1
//返回当前指定参数的相关位置
System.out.println(list.indexOf("a"));//运行结果:0 向前找
System.out.println(list.lastIndexOf("a"));//运行结果:2 向后找
//在指定位置插入元素
list.set(0,"petrel");
System.out.println(list);//运行结果:[petrel, 1, a, true] 插入前是[a, 1, a, true]
List list1 = list.subList(0, 2);
System.out.println(list1);//运行结果:[petrel, 1]
// List of = List.of(1,2,3,4); //这里要jdk12版本
// System.out.println(of);
}
}
package com.petrel;
import java.util.LinkedList;
/**
* @author Petrel
* @data 2020/6/23 9:52
*/
/**
* linkedList拥有更加丰富的方法实现,需要用的时候查询api即可,不需要记忆
*/
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(123);
linkedList.add(false);
linkedList.add("abc");
System.out.println(linkedList);//运行结果:[123, false, abc]
//在2的位置插入petrel
linkedList.add(2,"petrel");
System.out.println(linkedList);//运行结果:[123, false, petrel, abc]
//在头部插入元素
linkedList.addFirst("1111");
System.out.println(linkedList);//运行结果:[1111, 123, false, petrel, abc]
//在尾部插入元素
linkedList.addLast("2222");
System.out.println(linkedList);//运行结果:[1111, 123, false, petrel, abc, 2222]
//获取第一个元素
System.out.println(linkedList.element());//运行结果:1111
//添加元素
linkedList.offer("3333");
System.out.println(linkedList);//运行结果:[1111, 123, false, petrel, abc, 2222, 3333]
//indexOf获取元素所在位置
System.out.println(linkedList.indexOf(123));//运行结果:1
/**
* poll,peek,element的共同点:
* 都是返回队列中的首个元素
* 不同点:
* poll:将首个元素从队列中弹出,如果队列是空的,就返回null
* peek:查看首个元素,不会移除首个元素,如果队列是空的就返回null
* element:查看首个元素,不会移除首个元素,如果队列是空的就抛出异常NoSuchElementException
*/
//peek和peekFirst方法是一样的
System.out.println(linkedList.peek());//运行结果:1111
System.out.println(linkedList.poll());//运行结果:1111
System.out.println(linkedList.element());//运行结果:123 因为poll将首个元素从队列中弹出了
LinkedList linkedList1 = new LinkedList();
System.out.println(linkedList1.peek());//运行结果:null
System.out.println(linkedList1.poll());//运行结果:null
System.out.println(linkedList1.element());//运行结果:Exception in thread "main" java.util.NoSuchElementException
}
}
package com.petrel;
import java.util.Vector;
/**
* @author Petrel
* @data 2020/6/23 10:44
*/
/**
* 1、Vector也是List接口的一个子类实现
* 2、Vector跟ArrayList一样,底层都是使用数组进行实现的
* 3、面试经常问区别:
* (1)ArrayList是线程不安全的,效率高 Vector是线程安全的,效率低
* (2)ArrayList在进行扩容的时候,是扩容1.5倍,Vector扩容的时候扩容原来的2倍
*
* */
public class VectorDemo {
public static void main(String[] args) {
Vector vector = new Vector();
vector.add(1);
vector.add("abc");
System.out.println(vector);//运行结果:[1, abc]
}
}
Iterator 接口
package com.petrel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
/**
* @author Petrel
* @data 2020/6/23 11:00
*/
/*
* 在java代码中包含三种循环的方式
* do...while
* while
* for
* 还有一种增强for循环的方式,可以简化循环的编写
*
*
* 所有的集合类都默认实现了Iterable的接口,实现此接口意味着具备了增强for循环的能力,也就是for-each
*
* 增强for循环本质上使用的也是iterator的功能
* 方法:
* iterator() //这个的返回值是一个接口
* foreach()
*
* 在iterator的方法中,要求返回一个Iterator的接口子类实例对象
* 此接口中包含了
* hasNext() //判断集合中是否有值
* next() //有值的话 调用next()方法返回
* hasNext()+next()实现了一个集合的遍历过程
*
* Iterable -> iterator() -> hasNext()+next()
*
* ListIterator 继承了Iterator,以允许双向遍历列表和修改元素。
* 通过原码:cursor = lastRet; lastRet = -1; 知道这样就不会出错
* 在使用iterator进行迭代的过程中如果删除其中的某个元素会报错,并发操作异常,因此
* 如果遍历的同时需要修改元素,建议使用listIterator()
*
* ListIterator迭代器提供了向前和向后两种遍历的方式
* 始终是通过cursor和lastret的指针来获取元素值及向下的遍历索引
* 当使用向前遍历的时候必须要保证指针在迭代器的结果,否则无法获取结果值
* */
public class IteratorDemo {
public static void main(String[] args) {
ArrayList list= new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for(int i=0;i<list.size();i++){
System.out.println("1"+list.get(i)); //运行结果:1 2 3 4
}
//迭代器
/* Iterator iterator = list.iterator();
while(iterator.hasNext()){
//System.out.println(iterator.next());
Object o = iterator.next();
if(o.equals(1)){
//list.remove(o); 这样会报错ConcurrentModificationException并发修改异常 这里是因为存放的是数组 删除一个后下面的会往上移 就数据错误了
}
System.out.println(o);*/
ListIterator iterator1 = list.listIterator();//上面的list方法不能修改 这里改成ListIterator
while(iterator1.hasNext()){
Object l = iterator1.next();
if(l.equals(1)){
iterator1.remove();//这里变成了iterator 运行成功的原因:之前list和迭代器都操作,两个对象同时操作同一波数据集合指针就乱掉了,现在整个操作过程中用迭代器一个对象
}
System.out.println(l); //运行结果:1 2 3 4
//这里本来应该是向后遍历 运行结果是4 3 2,但是没运行出来┭┮﹏┭┮,要注意的是向后遍历的时候要先有从前往后的遍历
while (iterator1.hasPrevious()){
System.out.println("*"+iterator1.previous());
}
//增强for循环 使用较多
for (Object i : list){
System.out.println(i);//运行结果:2 3 4
}
}
}
}
HashSet
package com.petrel.dog;
import java.util.Objects;
/**
* @author Petrel
* @data 2020/6/24 9:05
*/
public class Dog {
private String name;
private String color;
public Dog(){
}
public Dog(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dog dog = (Dog) o;
return Objects.equals(name, dog.name) &&
Objects.equals(color, dog.color);
}
@Override
public int hashCode() {
return Objects.hash(name, color);
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}
------------
package com.petrel.dog;
import java.util.ArrayList;
import java.util.List;
/**
* @author Petrel
* @data 2020/6/24 9:07
*/
public class ListTest {
public static void main(String[] args) {
List list = new ArrayList();
Dog d1 = new Dog("皮","白色");
Dog d2 = new Dog("皮皮","黑色");
Dog d3 = new Dog("皮皮皮","黑白色");
list.add(d1);
list.add(d2);
list.add(d3);
System.out.println(list);//运行结果:[Dog{name='皮', color='白色'}, Dog{name='皮皮', color='黑色'}, Dog{name='皮皮皮', color='黑白色'}]
System.out.println(list.size());//运行结果:3
list.remove(d1);
System.out.println(list);//运行结果:[Dog{name='皮皮', color='黑色'}, Dog{name='皮皮皮', color='黑白色'}]
System.out.println(list.contains(d2));//运行结果:true
Dog d4 = new Dog("皮皮","黑色");
//System.out.println(list.contains(d4));//运行结果:false 原因:d4只是值和d2相同 并没有在list里面
//在Dog里面加了equals(Object o)和hashCode()之后
System.out.println(list.contains(d4));//运行结果:true 现在对应的是具体的值
}
}
Set 接口
package com.petrel;
import java.util.*;
/**
* @author Petrel
* @data 2020/6/24 9:18
*/
/**
* 1、set中存放的是无序,唯一的数据
* 2、set不可以通过下标获取对应位置的元素的值,因为无序的特点
* 3、使用treeset底层的实现是treemap,利用红黑树来进行实现
* 4、设置元素的时候,如果是自定义对象,会查找对象中的equals和hashcode的方法,如果没有,比较的是地址
* 5、树中的元素是要默认进行排序操作的,如果是基本数据类型,自动比较,如果是引用类型的话,需要自定义比较器
* 比较器分类:
* 内部比较器
* 定义在元素的类中,通过实现comparable接口来进行实现
* 外部比较器
* 定义在当前类中,通过实现comparator接口来实现,但是要将该比较器传递到集合中(添加了一个泛型)
* 注意:外部比较器可以定义成一个工具类,此时所有需要比较的规则如果一致的话,可以复用,而
* 内部比较器只有在存储当前对象的时候才可以使用
* 如果两者同时存在,使用外部比较器
* 当使用比较器的时候,不会调用equals方法
*/
public class SetDemo implements Comparator<Person> {
public static void main(String[] args) {
Set set = new HashSet(); //hash表是%存放
set.add("123");
set.add(1);
set.add("123");
set.add(true);
System.out.println(set); //运行结果:[1, 123, true] 无序、唯一
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());//运行结果:1 123 true
}
//将while循环改成for循环,推荐使用,节省了内存空间 因为while那里定义的迭代器作用对象是整个方法体
for(Iterator iter = set.iterator(); iter.hasNext();){
System.out.println(iter.next());//运行结果:1 123 true
}
//set.forEach();
//红黑树 分支左小右大
TreeSet treeSet = new TreeSet();
treeSet.add(2);
treeSet.add(12);
treeSet.add(8);
System.out.println(treeSet);//运行结果:[2, 8, 12]
System.out.println(treeSet.ceiling(9));//运行结果:12 返回集合中最小元素或大于等于给定的元素 如果没有返回null
HashSet hashSet = new HashSet();
hashSet.add(new Person("zhangsan",12));
hashSet.add(new Person("zhangsan",12));
hashSet.add(new Person("lisi",13));
System.out.println(hashSet);//运行结果:①没有加equals(Object o)和hashCode():[com.petrel.Person@74a14482, com.petrel.Person@4554617c, com.petrel.Person@1540e19d] ②加了之后:[com.petrel.Person@a8e9e1d9, com.petrel.Person@623659b]
//树中的元素是要默认进行排序操作的,如果是基本数据类型,自动比较,如果是引用类型的话,需要自定义比较器
//内部比较器
//定义在元素的类中,通过实现comparable接口来进行实现
//1.先将Person引入Comparable接口2.改写compareTo方法
TreeSet treeSet1 = new TreeSet();
treeSet1.add(new Person("lisi",15));
treeSet1.add(new Person("wangwu",13));
treeSet1.add(new Person("maliu",12));
treeSet1.add(new Person("zhangsan",19));
treeSet1.add(new Person("zhangsan",12));
System.out.println(treeSet1);//运行结果:[Person{name='lisi', age=15}, Person{name='maliu', age=12}, Person{name='wangwu', age=13}, Person{name='zhangsan', age=19}](按姓名的长度排序)
//外部比较器
//定义在当前类中,通过实现comparator接口来实现,但是要将该比较器传递到集合中
//1.SetDemo添加implements Comparator<Person> 2.改写compare方法
TreeSet treeSet2 = new TreeSet(new SetDemo()); //相对于内部比较器 这里多了一个new SetDemo()
treeSet2.add(new Person("lisi",15));
treeSet2.add(new Person("wangwu",13));
System.out.println(treeSet2);
}
@Override
public int compare(Person o1, Person o2) {
if(o1.getAge()>o2.getAge()){
return 1;
}else if(o1.getAge() < o2.getAge()){
return -1;
}else{
return 0;
}
}
}
Comparable 接口
package com.petrel;
import java.util.Objects;
/**
* @author Petrel
* @data 2020/6/24 11:43
*/
public class Person implements Comparable{
private String name;
private int age;
public Person(){
}
public Person(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 boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
/**
* 此比较器按照name的长度来进行比较
* @param o
* @return
*/
@Override
public int compareTo(Object o) {
Person p = (Person) o;
if (p.name.length()>this.name.length()){
return -1; //如果名字长的放前面 这里改成reture 1;
}else if(p.name.length()<this.name.length()){
return 1; //如果名字长的放前面 这里改成reture -1;
}else{
return 0;
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Map 接口
package com.petrel.map;
import java.util.*;
/**
* @author Petrel
* @data 2020/6/24 19:48
*/
/**
* map存储的是k-v键值对映射的数据
* 实现子类:
* HashMap:数据+链表(jdk1.7) 数组+链表+红黑树(jdk1.8)(数据结构 怎么存储的)
* LinkedHashMap:链表
* TreeMap:红黑树
*
* 基本api操作:
* 增加:
* put(k,v) 添加元素
* 查找:
* isEmpty 判断是否为空
* size 返回map的大小
* containsKey 包含key
* containsValue 包含value
* get
* 删除:
* clear 清空集合中的所有元素
* remove:删除指定元素
* Map.entry:表示的是K-V组合的一组映射关系,key和value成组出现
*
* hashmap跟hashtable的区别:
* 1、hashmap线程不安全,效率比较高,hashtable线程安全,效率低
* 2、hashmap中key和value都可以为空,hashtable不允许为空
*
*
* hashmap初始值为2的N次幂,
* 1、方便进行&操作,提高效率,&要比取模运算效率要高
* hash & (initCapacity-1)
* 2、在扩容之后涉及到元素的迁移过程,迁移的时候只需要判断二进制的前一位是0或者是1即可
* 如果是0,表示新数组和就数组的下标位置不变,如果是1,只需要将索引位置加上旧的数组的长度值即为新数组的下标
* 1.7源码知识点: 数组+链表
* 1、默认初始容量
* 2、加载因子
* 3、put操作
* 1、设置值,计算hash
* 2、扩容操作
* 3、数据迁移的过程
* * static final float DEFAULT_LOAD_FACTOR = 0.75f; 加载因子
* * this.threshold = tableSizeFor(initialCapacity); 设置初始容量值
* * return h`(h>>>7)`(h>>>4) ;减少哈希碰撞
* * new Entry 是new了一个对象 包括了key、value、next、hash
* * resize 扩容 包含了数据移动的功能
* * get是头插法
*
* 1.8源码知识点: 数组+链表+红黑树
* Entry变成了Node
*/
public class MapDemo {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("a",1);
map.put("b",2);
map.put("c",3);
map.put("d",4);
// map.put(null,null);//hashmap中key和value都可以为空
System.out.println(map); //运行结果:{a=1, b=2, c=3, d=4}
System.out.println(map.isEmpty()); //运行结果:false 不为空
System.out.println(map.size());//运行结果:4 返回map的大小
System.out.println(map.containsKey("a")); //运行结果:true
System.out.println(map.containsValue("2")); //运行结果:true
System.out.println(map.get("a")); //运行结果:1
map.remove("a");
System.out.println(map);//运行结果:{b=2, c=3, d=4}
//遍历操作
Set<String> keys = map.keySet();
for (String key:keys){
System.out.println(key+"="+map.get(key));//运行结果:b=2 c=3 d=4
}
//只能获取对应的value值,不能根据value来获取key
Collection<Integer> values = map.values();
for (Integer i : values){
System.out.println(i);//运行结果:2 3 4
}
//迭代器
Set<String> keys1 = map.keySet();
Iterator<String> iterator = keys1.iterator();
while (iterator.hasNext()){
String key = iterator.next();
System.out.println(key+"="+map.get(key)); //运行结果:b=2 c=3 d=4
}
//Map.entry:表示的是K-V组合的一组映射关系,key和value成组出现
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator();
while (iterator1.hasNext()){
Map.Entry<String,Integer> next = iterator1.next();
System.out.println(next.getKey()+"-"+next.getValue()); //运行结果:b-2 c-3 d-4
}
}
}
Collections工具类
package com.petrel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @author Petrel
* @data 2020/6/26 10:14
*/
//Collections工具类
public class CollectionsDemo {
public static void main(String[] args) {
//addAll批量添加
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
Collections.addAll(list, "e", "f", "....."); //添加不定长元素 可以加很多
System.out.println(list);//运行结果:[a, b, c, d, e, f, .....]
//sort1排序
List<String> list1 = new ArrayList<String>();
list1.add("af");
list1.add("bg");
list1.add("acssf");
list1.add("bdfsdfsd");
Collections.addAll(list1, "cefsdf", "cf1", "cg32");
list1.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (o1.length() > o2.length()) {
return 1;
} else if (o1.length() < o2.length()) {
return -1;
} else {
return 0;
}
}
});
System.out.println(list1);//运行结果:[af, bg, cf1, cg32, acssf, cefsdf, bdfsdfsd]
//sort2排序
Collections.sort(list1);//按照字母的顺序排序
System.out.println(list1);//运行结果:[acssf, af, bdfsdfsd, bg, cefsdf, cf1, cg32]
//sort3排序
Collections.sort(list1);
Collections.sort(list1,new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if(o1.length()>o2.length()){
return 1;
}else if(o1.length()<o2.length()){
return -1;
}else{
return 0;
}
}
});
System.out.println(list1);//运行结果:[af, bg, cf1, cg32, acssf, cefsdf, bdfsdfsd]
//binarySearch()二分查找 需要先进行排序操作,如果没有排序的话,是找不到指定元素的(自己排序)
System.out.println(Collections.binarySearch(list,"b"));//运行结果:1
//fill替换
Collections.fill(list,"petrel");
System.out.println(list);//运行结果:[petrel, petrel, petrel, petrel, petrel, petrel, petrel]
//shuffle()随机排序
Collections.shuffle(list1);
System.out.println(list1);//运行结果:[cg32, bg, cf1, acssf, cefsdf, af, bdfsdfsd]
//reverse()
Collections.reverse(list1);
System.out.println(list1);//运行结果:[bdfsdfsd, af, cefsdf, acssf, cf1, bg, cg32] 与上一行的运行结果逆序
}
}
Arrays
package com.petrel;
/**
* @author Petrel
* @data 2020/6/26 10:45
*/
import java.util.Arrays;
import java.util.List;
/**
* Arrays提供了数据操作的工具类,包含很多方法
* 集合和数组之间的转换
* 数组转成list:
*
*/
public class ArraysDemo {
public static void main(String[] args) {
//int[] array = new int[]{1,2,3,4,5};
List<Integer> ints = Arrays.asList(1,2,3,4,5); //List类型的数组
//list转换成数组
//ints.toArray().var;
Object[] objects = ints.toArray();
}
}
泛型
package com.petrel.fanxing;
import com.petrel.Person;
import java.util.ArrayList;
import java.util.List;
/**
* @author Petrel
* @data 2020/6/24 15:11
*/
/**
* 当做一些集合的统一操作的时候,需要保证集合的类型是统一的,此时需要泛型来进行限制
* 优点:
* 1、数据安全
* 2、获取数据时效率比较高
* 给集合中的元素设置相同的类型就是泛型的基本需求
* 使用:
* 在定义对象的时候,通过<>中设置合理的类型来进行实现
* 泛型的高阶应用:
* 1、泛型类
* 在定义类的时候在类名的后面添加<E,K,V,A,B>,起到占位的作用,类中的方法的返回值类型和属性的类型都可以使用
* 2、泛型接口
* 在定义接口的时候,在接口的名称后添加<E,K,V,A,B>,
* 1、子类在进行实现的时候,可以不填写泛型的类型,此时在创建具体的子类对象的时候才决定使用什么类型
* public class FanXingInterfaceSub<B> implements FanXingInterface<B>
* 2、子类在实现泛型接口的时候,只在实现父类的接口的时候指定父类的泛型类型即可,此时,测试方法中的泛型类型必须要跟子类保持一致
* public class FanXingInterfaceString implements FunctionalInterface<String>
*
* 3、泛型方法
* 在定义方法的时候,指定方法的返回值和参数是自定义的占位符,可以是类名中的T,也可以是自定义的Q,只不过在使用Q的时候需要使用<
* Q>定义在返回值的前面
* 4、泛型的上限(工作中不用)
* 如果父类确定了,所有的子类都可以直接使用
* 5、泛型的下限(工作中不用)
* 如果子类确定了,子类的所有父类都可以直接传递参数使用
*
*/
public class FanXingDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(); //加<String>限制是String类型,这就是泛型
list.add("ABC");
list.add("1");
System.out.println(list);//运行结果:[ABC, 1]
FanXingClass<String> fxc = new FanXingClass<>();
fxc.setA("petrel");
fxc.setId(1);
fxc.show();//运行结果:id : 1 ,A : petrel
FanXingClass<Integer> fxc2 = new FanXingClass<>();
//fxc2.setA("petrel"); 这样会报错 因为现在A是Integer类型
fxc2.setA(34);
fxc2.setId(2);
fxc2.show();//运行结果:id : 2 ,A : 34
FanXingClass<Person> fxc3 = new FanXingClass<>();
fxc3.setA(new Person("a",2));
fxc3.setId(3);
fxc3.show();//运行结果:id : 3 ,A : Person{name='a', age=2}
System.out.println(fxc3.get());//运行结果:Person{name='a', age=2}
fxc3.set(new Person("hhe",123));//运行结果:执行set方法:Person{name='hhe', age=123}
FanXingInterfaceSub fxi = new FanXingInterfaceSub();
fxi.test2(13);
FanXingMethod<String> fxm = new FanXingMethod<>();
fxm.setT("aa");
fxm.show(123); //运行结果:123 aa
fxm.show(true); //运行结果:true aa
}
}
package com.petrel.fanxing;
/**
* @author Petrel
* @data 2020/6/24 15:20
*/
//泛型类
public class FanXingClass<A> {
private int id;
private A a; //不知道是什么类型的时候就定义一个泛型
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
public void show(){
System.out.println("id : "+id+" ,A : "+a);
}
public A get(){
return a;
}
public void set(A a){
System.out.println("执行set方法:" + a);
}
}
package com.petrel.fanxing;
//泛型接口
public interface FanXingInterface<B> {
public B test();
public void test2(B b);
}
package com.petrel.fanxing;
/**
* @author Petrel
* @data 2020/6/24 15:47
*/
//子类在进行实现的时候,可以不填写泛型的类型,此时在创建具体的子类对象的时候才决定使用什么类型
public class FanXingInterfaceSub<B> implements FanXingInterface<B> {
@Override
public B test() {
return null;
}
@Override
public void test2(Object o) {
System.out.println(o);
}
}
package com.petrel.fanxing;
/**
* @author Petrel
* @data 2020/6/24 16:27
*/
//泛型方法
//好处:输入的类型根据参数决定
public class FanXingMethod<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public <Q> void show(Q q){
System.out.println(q);
System.out.println(t);
}
}