ListMap集合
List集合
List接口
- 继承于Collection接口
- 有序可重复原则,集合中每个元素具有对应的索引,可以通过索引直接访问该元素
- List集合默认按照添加元素的顺序设置索引
- List集合关心是否有序但并不关心是否重复
- List接口的实现类由ArrayList动态数组、Vector动态数组、LinkedList双向链表、Stack栈
List集合针对索引的方法
1、添加元素
- void add(int index, Object element):将元素element插入到List集合的index处。
- boolean addAll(int index, Collection c):将集合c所包含的所有元素都插入到List集合的index处。
2、获取元素
- Object get(int index): 返回集合index索引处的元素。
- List subList(int fromIndex, int toIndex):返回从索引 fromlndex (包含)到索引toIndex(不包含)处所有集合元素组成的子集合。
3、获取元素索引
- int indexOf(Object obj):返回对象。在List集合中第一次出现的位置索引。
- int lastIndexOf(Object obj):返回对象。在List集合中最后一次出现的位置索引。
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("詹姆斯");
list.add("韦德");
list.add("欧文");
list.add("杜兰特");
list.add("西蒙斯");
System.out.println(list);
list.add(3,"哈登");//添加到欧文之后
System.out.println(list);
System.out.println(list.get(4));获取指定索引位置处的元素---->杜兰特
System.out.println(list.subList(1,3));//返回两个索引之间的元素作为子集合输出,不包含后一个索引位置处的元素
list.add("詹姆斯");
list.add("詹姆斯");
list.add("詹姆斯");
System.out.println(list);
System.out.println(list.indexOf("詹姆斯"));//获取“詹姆斯”在集合中第一次出现的索引
System.out.println(list.lastIndexOf("詹姆斯"));//获取“詹姆斯”在集合中最后一次出现的索引
list.remove(1);//删除1处索引元素“韦德”
System.out.println(list);
list.set(4,"伦纳德");//将索引4处的西蒙斯换成伦纳德
System.out.println(list);
for (String s : list) {
System.out.print(s+" ");
}
}
重写equals方法判断
@Override
public boolean equals(Object o) {
//首先判断传入该方法的对象是否是E类对象
if (o instanceof E){
E obj = (E) o;//强制转换
if(this.getCount() == obj.getCount())
return true;//相等返回true 否则返回false
}
return false;
}
ListIterator
import java.util.ListIterator;//导包
List集合提供了一个额外的方法listiterator()方法用于返回一个iterator对象,ListIterator接口继承了Iterator接口,提供了操作List集合的方法,与Iterator不同的是,它可以双向移动而Iterator只能单向移动
常用方法:
- void add():通过迭代器添加元素到对应集合
- void set(Object obj):通过迭代器替换正迭代的元素
- void remove():通过迭代器删除刚迭代的元素
- boolean hasPrevious():如果以逆向遍历列表,往前是否还有元素。
- Object previous():返回列表中的前一个元素。
- int previousIndex():返回列表中的前一个元素的索引
- boolean hasNext()
- Object next()
- int nextIndex()
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
//首先进行正向遍历,可以把迭代器的遍历理解为具有一个指针,当正向遍历到最后一个元素时,在进行逆向遍历
ListIterator<String> iterator = list.listIterator();
while(iterator.hasNext()){
System.out.print(iterator.next()+" ");
}
System.out.println();
//逆向遍历
while(iterator.hasPrevious()){
System.out.print(iterator.previous()+" ");
}
//set方法使用
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
ListIterator<Integer> it = list.listIterator();
while (it.hasNext()){
Integer intt = it.next();
if (intt.equals(3)){
it.set(999);
}
}
System.out.println(list);
}
使用Listerator时注意处理并发异常现象
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
//下面代码演示Listiterator并发异常现象
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
list.add(1, "牛");
System.out.println(it.next());
}
//并发异常,使用迭代器遍历时不能使用集合对象修改集合数据
//java.util.ConcurrentModificationException
}
//逆向遍历
while(iterator.hasPrevious()){
System.out.print(iterator.previous()+" ");
}
LinkedList实现类
- LinkedList集合支持双链表,定位首尾元素速度较快,增删首尾元素速度快。
- 故而提供了多种API来操作LinkedList集合的首尾元素
- LinkedList与ArrayList不同的是,ArrayList的底层是数组实现,但LinkedList的底层是利用链表实现
LinkedList做队列
public static void main(String[] args) {
//LinkedList做队列使用 ---->先进先出,后进后出
LinkedList<String> queue = new LinkedList<>();
//入队
queue.addLast("一号");
queue.addLast("二号");
queue.addLast("三号");
queue.addLast("四号");
queue.addLast("五号");
System.out.println(queue);
//出队
System.out.println(queue.removeFirst());
System.out.println(queue.removeFirst());
System.out.println(queue);
}
LinkedList做栈
public static void main(String[] args) {
//LinkedList做栈使用---->先进后出,后进先出
//可以理解为装填子弹,第一颗装入之后装第二课,第二课将第一颗往下挤,第一颗位于首位,以此类推
LinkedList<String> stack = new LinkedList<>();
//压栈
stack.push("第一颗子弹");
stack.push("第二颗子弹");
stack.push("第三颗子弹");
stack.push("第四颗子弹");
//出栈
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack);
}
- 做栈使用时发现:
入栈方法push()与addFirst()是相同的效果,并且push()的底层实现也是调用了addFirst()
//push方法的底层实现 public void push(E e) { addFirst(e); }
出栈方法pop()与removeFirst()也是相同效果
//pop()方法底层实现 public E pop() { return removeFirst(); }
Map集合
概述
- Map集合是一种与Collection不同的集合体系,Collection是单列集合
- 与Collection集合相同的是,Map是所有双列集合的父接口
- 其实现类有HashMap、TreeMap、LinkedHashMap
- Map集合是双列集合,它每个元素包含两个数据,即“键key”和“值value”
- Map集合也成为键值对集合,每个元素的格式:key=value
- Map集合的完整格式:Map<k,v>
{key1=value1,key2=value2,key3=value3,...}
- 与Set集合相同:无序、不重复、无索引、值可以为空
- 不重复:后面添加的元素在前面若有重复则会覆盖掉之前的元素
- Map集合的特点由键key决定
- Set集合的底层实现就是利用了Map集合
Set<String> sets = new HashSet<>();
/*HashSet底层就是HashMap集合
public HashSet() {
map = new HashMap<>();
}*/
Set<Integer> integerSet = new TreeSet<>();
/*TreeSet底层实现就是TreeMap集合
public TreeSet() {
this(new TreeMap<E,Object>());
}*/
常用API*
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
//1. 添加元素
maps.put("Benz",4);
maps.put("Ferrari",5);
maps.put("Lamborghini",13);
maps.put("Maserati",7);
System.out.println(maps);
//2. 清空Map集合
//maps.clear();
//System.out.println(maps);
//3. 判断集合是否为空,是返回true,反之false
System.out.println(maps.isEmpty());//true
//4. 根据键key获取对应值value
Integer temp = maps.get("Maserati");
System.out.println(temp);
//5. 根据键删除整个元素---->删除键key返回值
maps.remove("Benz");
System.out.println(maps);
//6. 判断是否包含某个键key
System.out.println(maps.containsKey("Benz"));
//7. 判断是否包含某个值
System.out.println(maps.containsValue(7));
//8. 获取全部键key的集合-----> public set<k> keySet()
//map集合是无需不重复,返回的是set集合
//写法一:
System.out.println(maps.keySet());
//写法二:
Set<String> keys = maps.keySet();
for (String key : keys) {
System.out.print(key+" ");
}
System.out.println();
//9. 获取全部值value的集合----->public Collection<v> values()
//Map集合值不做要求,值value可以重复,所以要用Collection集合接收并返回
//写法一:
System.out.println(maps.values());
//写法二:
Collection<Integer> values = maps.values();
for (Integer value : values) {
System.out.print(value+" ");
}
System.out.println();
//10. 获取集合的大小
System.out.println(maps.size());
//11. 合并其他Map集合
Map<String,Integer> mapss = new HashMap<>();
mapss.put("Mi",2);
mapss.put("iPhone",2);
mapss.put("华为",2);
mapss.put("MEIZU",2);
//将mapss集合全部注入maps集合中即大小size变成7
maps.putAll(mapss);
System.out.println(maps.size());//3--->7
}
Map集合遍历
- 通过键key来获取每个值
public static void main(String[] args) {
//通过键找值
Map<String,Integer> maps = new HashMap<>();
maps.put("Benz",4);
maps.put("Ferrari",5);
maps.put("Lamborghini",13);
maps.put("Maserati",7);
//调用KeySet方法拿到键的Set集合
Set<String> keyset = maps.keySet();
//遍历键集合,通过调用get方法获取每个键的value值
for (String key : keyset) {
Integer value = maps.get(key);
System.out.println(key+" = "+value);
}
}
- 通过Set<Map.Entry<k,v>>和entrySet方法将Map集合打成Set集合再进行遍历
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("Benz",4);
maps.put("Ferrari",5);
maps.put("Lamborghini",13);
maps.put("Maserati",7);
/*
正常情况下,可以利用foreach遍历set、list等单列集合,因为单列集合中的元素有自己特定的数据类型
但是map集合中的元素是一个键值对,没有自己的数据类型也就不能直接通过foreach遍历
故而把Map集合通过Set<Map.Entry<k,v>> entrySet转换城Set集合进行遍历
Map.Entry是Map集合的一个实体类型,换而言之
Map.Entry就是<key,value>的数据类型
此时将key和value键值对看作一个整体
查看Entry底层源码发现,Entry具有能够直接获取Map集合Key与Value的方法
interface Entry<K,V> {
K getKey();
V getValue();
*/
Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
for (Map.Entry<String, Integer> stringIntegerEntry : entrySet) {
String strEntry = stringIntegerEntry.getKey();
Integer intEntry = stringIntegerEntry.getValue();
System.out.println(strEntry+"=>"+intEntry);
//System.out.print(stringIntegerEntry+" ");
}
}
Map集合存储自定义类型元素
class Student{
private String name;
private int age;
public Student() {}
public Student(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 "Student {"+name+age+"岁"+"}";}
}
public class TestMain {
//将学生与班级进行对应 学生作为键,班级作为值
public static void main(String[] args) {
Map<Student,Integer> studentMessage = new HashMap<>();
studentMessage.put(new Student("张三",19),2250);
studentMessage.put(new Student("李四",21),2266);
studentMessage.put(new Student("王五",20),2266);
studentMessage.put(new Student("赵六",17),2266);
studentMessage.put(new Student("冯七",22),2250);
Set<Map.Entry<Student,Integer>> entrySet = studentMessage.entrySet();
for (Map.Entry<Student, Integer> studentIntegerEntry : entrySet) {
System.out.println(studentIntegerEntry);
}
}
}
TreeMap
- TreeMap作为TreeSet的底层实现,仍然是两种排序方式即自然排与定制排
- 自然排序
public static void main(String[] args) {
Map<Integer,String> studentMessage = new TreeMap<>();
studentMessage.put(47,"1");
studentMessage.put(22,"2");
studentMessage.put(39,"3");
studentMessage.put(10,"4");
studentMessage.put(1,"4");
//默认升序排序
/*
key=1value4
key=10value4
key=22value2
key=39value3
key=47value1
*/
studentMessage.forEach((k,v)-> System.out.println("key="+k+"value"+v));
}
- 定制排序一:
- 此类实现Comparable接口,并且重写CompareTo比较方法
class R implements Comparable<R>{
private String name;
private int age;
public R(){}
public R(String name,int age){this.name=name;this.age=age;}
public void setName(String name){this.name=name;}
public void setAge(int age){this.age=age;}
public String getName(){return name;}
public int getAge(){return age;}
public String toString(){return "姓名:"+name+" 年龄"+age;}
public int compareTo(R o){
//按照年龄排序--->降序
return Integer.compare(o.age,this.age);
}
}
public class TestMain {
public static void main(String[] args) {
Map<R,String> maps = new TreeMap<>();
maps.put(new R("张三",25),"GZ2266期");
maps.put(new R("李四",36),"GZ2250期");
maps.put(new R("王五",67),"GZ2266期");
maps.put(new R("汪苏泷",33),"GZ2250期");
maps.put(new R("刘德华",51),"GZ2250期");
maps.put(new R("吴京",42),"GZ2250期");
maps.forEach((k,v)-> System.out.println("key:"+k+"value:"+v));
}
}
- 定制排序二:
- 利用匿名内部类写法,向TreeMap集合中注入Comparator比较器,并且重写compare比较方法
class R{
private int count;
public R(){}
public R(int count){this.count=count;}
public void setCount(int count){this.count=count;}
public int getCount(){return count;}
@Override
public String toString() {return "R{" + "count=" + count + '}';}
}
public class TestMain {
public static void main(String[] args) {
Map<R,String> maps = new TreeMap<>(new Comparator<R>() {
@Override
public int compare(R o1, R o2) {
//按照降序
return o2.getCount() - o1.getCount();
}
});
maps.put(new R(1),"1");
maps.put(new R(2),"2");
maps.put(new R(3),"3");
maps.put(new R(4),"4");
maps.put(new R(5),"5");
System.out.println(maps);
/*{R{count=5}=5, R{count=4}=4, R{count=3}=3, R{count=2}=2, R{count=1}=1}*/
}
}
LinkedHashMap
- HashSet有一个子类是LinkedHashSet,HashMap也有一个LinkedHashMap子类;
- LinkedHashMap也使用双向链表维护Map集合的键值对次序
public static void main(String[] args) {
Map<String,Integer> subjectScore = new LinkedHashMap<>();
subjectScore.put("语文",127);
subjectScore.put("数学",147);
subjectScore.put("英语",148);
subjectScore.put("理科综合",292);
subjectScore.put("口语",93);
//按照添加顺序输出
subjectScore.forEach((k,v)-> System.out.println("key="+k+"value="+v));
}