集合

什么情况使用集合框架?

​ 如果不知道程序运行时需要多少对象,或者需要更复杂的方式存储对象

比较重要的

学习路线

Collection类

import java.util.ArrayList;
import java.util.Collection;/*集合框架:Collection:存放的是单一值特点:1.可以存放不同类型的数据,而数组只能存放同一类型的数据2.当使用arrayList子类实现的时候,初始长度是10,当长度不够的时候,会进行自动扩容api方法(增,删,查):增加数据的方法add:要求必须传入的参数是Object对象,因此当写入基本是基本类型的时候,进行了装箱和拆箱,只不过过程不可见addAll:添加另一个集合的元素到此集合中删除数据的方法clear:只是清空集合中的元素,但是此集合对象并没有被回收remove:删除指定元素removeAll:删除指定集合retainAll:用于保留 arraylist 中在指定集合中也存在的那些元素,也就是删除指定集合中不存在的那些元素如果 arraylist 中删除了元素则返回 true。如果 arraylist 类中存在的元素与指定 collection 的类中元素不兼容,则抛出 ClassCastException 异常。如果 arraylist 包含 null 元素,并且指定 collection 不允许 null 元素,则抛出 NullPointerException 。查询数据的方法contains:判断集合中是否包含指定的元素值containsAll:判断集合中是否包含另一个集合isEmpty:判断集合是否为空size:返回当前集合的大小集合转数组的操作toArray:将集合转化成数组*/
public class CollectionDemo {public static void main(String[] args) {//Constructs an empty list with an initial capacity of ten.Collection collection = new ArrayList();//必须子类实现,接口无法newcollection.add(1);collection.add(true);collection.add(1.23);collection.add("abc");System.out.println(collection);((ArrayList)collection).add(0,"java");//强制类型转换System.out.println(collection);Collection collection1 = new ArrayList();collection1.add("a");collection1.add("b");collection1.add("c");collection1.add("d");collection.addAll(collection1);//将另一个集合全部元素添加进来System.out.println(collection);//        collection.clear();
//        System.out.println(collection);System.out.println(collection.contains("a"));System.out.println(collection.containsAll(collection1));System.out.println(collection.isEmpty());//        collection.remove("a");
//        System.out.println(collection);System.out.println(collection1.retainAll(collection));//false
//        System.out.println(collection.retainAll(collection1));// true 并且collection中只剩下[a, b, c, d],即collection1中所包含的元素Object[] objects = collection.toArray();//注意:如果不确定返回的类型,可以使用.var进行补全    collection.toArray().varcollection.add("a");System.out.println(collection);//[java, 1, true, 1.23, abc, a, b, c, d, a]  不唯一}
}

List和Set接口

Collection接口中存储一组不唯一无序的对象

List接口中存储一组不唯一有序的对象

Set接口中存储一组唯一无序的对象

Map接口中存储一组键值对象,提供keyvalue的映射

1.List接口的实现类

​ List特点:有序,不唯一

ArrayList 实现了长度可变的数组,在内存中分配连续空间

​ 优点:遍历元素和随机访问元素的效率比较高

​ 缺点:添加和删除需要大量移动元素效率低,按内容查询效率低

import java.util.ArrayList;
import java.util.List;/*集合框架:List特点:1.可以存放不同类型的数据,而数组只能存放同一类型的数据2.当使用arrayList子类实现的时候,初始长度是10,当长度不够的时候,会进行自动扩容api方法(增,删,查):继承Collectionget:输出指定下标的元素indexOf:输出指定元素的下标(从前往后找)lastIndexOf:输出指定元素的下标(从后往前找)set:将此列表中指定位置的元素替换为指定元素subList:截取指定下标元素到新的集合中jdk9中新增了一个of方法:可以给集合一次性添加多个元素List of = List.of(1,2,3,4);结果为:[1,2,3,4]使用前提:当集合中存储的元素个数已经确定了,不再改变时使用。注意:1.of方法只适用于List接口,Set接口,Map接口,不适用于接口的实现类2.of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常3.Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常*/
public class CollectionDemo {public static void main(String[] args) {List list = new ArrayList();list.add("a");list.add(1);list.add(true);list.add("a");System.out.println(list);System.out.println(list.get(0));//输出指定下标的元素System.out.println(list.indexOf("a"));//输出指定元素的下标(从前往后找)System.out.println(list.lastIndexOf("a"));//输出指定元素的下标(从后往前找)list.set(0, "java");//将此列表中指定位置的元素替换为指定元素System.out.println(list);//[a, 1, true, a]->[java, 1, true, a]List list1 = list.subList(0, 2);//截取指定下标元素到新的集合中System.out.println(list1);//[java, 1]}
}

LinkedList采用链表存储方式

​ 优点:插入、删除元素效率比较高

​ 缺点:遍历和随机访问元素效率低下

import java.util.LinkedList;
/*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);linkedList.add(0, "java");System.out.println(linkedList);//LinkedList特有的头插和尾插linkedList.addFirst("first");linkedList.addLast("last");System.out.println(linkedList);System.out.println(linkedList.element());//获取对应的第一个元素linkedList.offer(33);//添加一个元素System.out.println(linkedList);}
}

2.Vector和ArrayList

**面试经常问区别:
** 1.ArrayList是线程不安全的,效率高;Vector是线程安全的,效率低
2.ArrayList在进行扩容的时候,扩容1.5倍;Vector在扩容的时候,扩容2倍

import java.util.Vector;
/*1.Vector也是List接口的一个子类实现2.Vector跟ArrayList一样,底层都是用数组进行实现的面试经常问区别: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(true);vector.add("123");System.out.println(vector);}
}

练习

import java.util.Objects;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;}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, color);}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", color='" + color + '\'' +'}';}
}
import java.util.ArrayList;
import java.util.List;public class ListTest {public static void main(String[] args) {List list = new ArrayList();Dog d1 = new Dog("大黄","red");Dog d2 = new Dog("二黄","black");Dog d3 = new Dog("三黄","green");list.add(d1);list.add(d2);list.add(d3);System.out.println(list);//[Dog{name='大黄', color='red'}, Dog{name='二黄', color='black'}, Dog{name='三黄', color='green'}]System.out.println(list.size());list.remove(d1);System.out.println(list);System.out.println(list.contains(d2));//扩展Dog d4 = new Dog("二黄","black");//此时d4返回什么?
//        System.out.println(list.contains(d4));//false  地址不一样//怎么把结果变成true----->重写equals和hasCode,将对比地址改为对比实际属性值System.out.println(list.contains(d4));//true}
}

Iterator接口

Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayListHashSet等集合。

Iterator 是 Java 迭代器最简单的实现,ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口。

迭代器 it 的基本操作是 next 、hasNext 和 remove

​ 调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。

​ 调用 it.hasNext() 用于检测集合中是否还有元素。

​ 调用 it.remove() 将迭代器返回的元素删除。

获取一个迭代器

集合想获取一个迭代器可以使用 iterator() 方法:

// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;public class RunoobTest {public static void main(String[] args) {// 创建集合ArrayList sites = new ArrayList();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");// 获取迭代器Iterator it = sites.iterator();// 输出集合中的第一个元素System.out.println(it.next());//Google}
}

循环集合元素

让迭代器 it 逐个返回集合中所有元素最简单的方法是使用 while 循环

while(it.hasNext()) {System.out.println(it.next());
}

删除元素

要删除集合中的元素可以使用 remove() 方法。

以下实例我们删除集合中小于 10 的元素:

// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;public class RunoobTest {public static void main(String[] args) {ArrayList<Integer> numbers = new ArrayList<Integer>();numbers.add(12);numbers.add(8);numbers.add(2);numbers.add(23);Iterator<Integer> it = numbers.iterator();while(it.hasNext()) {Integer i = it.next();if(i < 10) {  it.remove();  // 删除小于 10 的元素}}System.out.println(numbers);//[12, 23]}
}

关于解决使用remove出现的并发操作异常的问题

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;/*在java代码中包含三种循环的方式do...while、for、while还有一种增强for循环的方式,可以简化循环的编写在所有的集合类,都默认实现了Iterable的接口,实现此接口意味着具备了实现增强for循环的能力增强for循环本质上是用的也是interator迭代器的功能方法:iterator()forEach()在iterator()方法中要求返回一个Iterator的接口子类实例化对象此接口中包含了:hasNext()next()实现了Iterable的接口,当调用它的时候返回一个迭代器iterator(),迭代器iterator()也是一个接口对象,实现出来后用来调用hasNext()和next()在使用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(list.get(i));
//        }//迭代器
//        Iterator iterator = list.iterator();//并发操作异常
//        while (iterator.hasNext()){//            Object o = iterator.next();
//            if(o.equals(1)){//                list.remove(1);
//            }
//            System.out.println(o);ListIterator iterator = list.listIterator();while (iterator.hasNext()){Object o = iterator.next();if(o.equals(1)){iterator.remove();}System.out.println(o);}System.out.println("-------------");while (iterator.hasPrevious()){System.out.println(iterator.previous());}//简便写法System.out.println("------------------");for (Object i : list){System.out.println(i);}}
}

Set接口

HashSet采用HashTable哈希表存储结构

​ 优点:添加速度快,查询速度快,删除速度快

​ 缺点:无序

LinkedHashSet

​ 采用哈希表存储结构,同时使用链表维护次序

​ 特点:有序

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/*1.set中存放的是无序,唯一的数据2.set不可以通过下标获取对应的元素的值,因为它是无序的*/
public class SetDemo {public static void main(String[] args) {Set set = new HashSet();set.add(123);set.add("abc");set.add(true);System.out.println(set);//[abc, 123, true]  无序set.add(123);System.out.println(set);//[abc, 123, true]  唯一Iterator iterator = set.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}System.out.println("--------------------------");//将while循环改成for循环for(Iterator iter = set.iterator();iter.hasNext();){System.out.println(iter.next());}//推荐使用此种方式}
}

TreeSet采用二叉树(红黑树)的存储结构

​ 优点:有序(排序后升序),查询速度比List快

​ 缺点:查询速度没有HashSet

红黑树简介

是一种自平衡二叉树,相比于平衡二叉树(AVL树),红黑树牺牲了部分平衡性以换取插入、删除时少量的旋转操作,整体来说性能要优于AVL树

特点:

​ 1.节点是红色或者黑色

​ 2.根节点是黑色

​ 3.每个叶节点(NIL节点)是黑色

​ 4.从任意节点到其每个叶子的所有路径都包含相同数目的黑色节点

​ 5.每个红色节点的两个子节点都为黑色(从每个叶子节点到根的路径上不能有两个连续的红色节点)

​ 6.最长路径不超过最短路径的两倍

例如:

TreeSet和HashSet

import java.util.Objects;public class Person {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;}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;/*1.set中存放的是无序,唯一的数据2.set不可以通过下标获取对应的元素的值,因为它是无序的3.设置元素的时候,如果是自定义对象,会查找对象中的equals和hashcode的方法,如果没有,比较的是地址*/
public class SetDemo {public static void main(String[] args) {//        TreeSet treeSet = new TreeSet();//存储数据结构:红黑树
//        treeSet.add(123);
//        treeSet.add(2);
//        treeSet.add(7);//必须是相同的数据类型
//        System.out.println(treeSet.ceiling(3));//返回此集合中最小元素大于或等于给定元素,如果没有此元素,则返回 null 。
//        System.out.println(treeSet);HashSet hashSet = new HashSet();//用hasMap实现hashSet.add(new Person("张三",12));hashSet.add(new Person("张三",12));hashSet.add(new Person("李四",13));hashSet.add(new Person("王五",14));hashSet.add(new Person("赵六",15));System.out.println(hashSet);}
}

自建类如何让hashSet判断输入内容是否相同

import java.util.Objects;/*为了提高比较的效率,会根据内容算出一个hash值,用hash值来判断是否相同,效率会提升但hash值是不安全的,hash值一致但内容不一定相同如果出现hash值相同的情况,那么就必须使用equals()方法来判断内容是否相同hashCode()添加内容时先用key.hasCode(),计算hash值作比较,如果hash值相等equals()在调用key.equals(k)比较内容是否相等这样即保证了效率又保证了安全性*/
public class Students {private  int no;private String name;public Students(int no, String name) {this.no = no;this.name = name;}@Overridepublic String toString() {return "Students{" +"no=" + no +", name='" + name + '\'' +'}';}//重写@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Students students = (Students) o;return no == students.no &&Objects.equals(name, students.name);}@Overridepublic int hashCode() {return Objects.hash(no, name);}
}
import java.util.HashSet;public class HashSetDemo2 {public static void main(String[] args) {Students s1 = new Students(101, "jim1");Students s2 = new Students(102, "jim2");Students s3 = new Students(103, "jim3");Students s4 = new Students(101, "jim1");Students s5 = new Students(105, "jim5");HashSet<Students> set = new HashSet<>();set.add(s1);set.add(s2);set.add(s3);set.add(s4);set.add(s5);System.out.println(set);//输出5个//面试重点://[Students{no=103, name='jim3'}, Students{no=105, name='jim5'}, Students{no=102, name='jim2'}, Students{no=101, name='jim1'}, Students{no=101, name='jim1'}]//为什么?//因为Students并没有默认的equals()和hasCode()方法,因此去调用Object类中的//Object中的hasCode()//public native int hasCode():值是对象地址,对象地址是相同的//Object中的equals()//默认比较对象地址//解决方法:在自己的类中重写//输出4个//[Students{no=101, name='jim1'}, Students{no=102, name='jim2'}, Students{no=103, name='jim3'}, Students{no=105, name='jim5'}]}
}

Comparable接口

import java.util.Objects;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;}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}/*** 内部比较器* 此比较器按照age的长度进行比较* @param o* @return*/@Overridepublic int compareTo(Object o) {Person p = (Person)o;if(p.age>this.age){return 1;}else if(p.age<this.age){return -1;}else return 0;}
}
import java.util.*;/*树中的元素是要默认进行排序操作的,如果是基本类型的话,自动比较,如果是引用类型的话,需要自己自定义比较器比较器分类:内部比较器:定义在元素的类中,通过实现comparable接口来实现外部比较器:定义在当前类中,通过Comparator接口来实现,但是要将该比较器传到集合中外部比较器可以定义成一个工具类,此时所有需要比较的规则如果一致的话,可以复用,而内部比较器只有在存储当前对象的时候才可以使用如果两者同时存在,使用外部比较器*/
public class SetDemo implements Comparator<Person> {//外部比较器public static void main(String[] args) {//存储数据结构:红黑树TreeSet treeSet = new TreeSet(new SetDemo());//new SetDemo() 将外部比较器传入
//        treeSet.add(123);
//        treeSet.add(2);
//        treeSet.add(7);//必须是相同的数据类型
//        System.out.println(treeSet.ceiling(3));//返回此集合中最小元素大于或等于给定元素,如果没有此元素,则返回 null 。
//        System.out.println(treeSet);treeSet.add(new Person("张三",12));treeSet.add(new Person("张三",12));treeSet.add(new Person("李四",13));treeSet.add(new Person("王五",14));treeSet.add(new Person("赵六",15));System.out.println(treeSet);//运行报错,原因是运行的时候无法排序//解决方法,实现一个比较器Comparable(内部比较器)//[Person{name='赵六', age=15}, Person{name='王五', age=14}, Person{name='李四', age=13}, Person{name='张三', age=12}]//        HashSet hashSet = new HashSet();
//        hashSet.add(new Person("张三",12));
//        hashSet.add(new Person("张三",12));
//        hashSet.add(new Person("李四",13));
//        hashSet.add(new Person("王五",14));
//        hashSet.add(new Person("赵六",15));
//        System.out.println(hashSet);}@Overridepublic int compare(Person o1, Person o2) {if(o1.getAge()>o2.getAge()){return 1;}else if(o1.getAge()<o2.getAge()){return -1;}else return 0;}
}

泛型

基本概念

import java.util.ArrayList;
import java.util.List;
/*当做一些集合的统一操作的时候,需要保证集合的类型是统一的,此时需要泛型来进行控制优点:1.数据安全2.获取数据时效率较高因此给集合中的元素设置相同的类型就是泛型的基本需求使用:在定义对象的时候,通过<>中设置合理的类型来进行实现*/
public class FanXingDemo {public static void main(String[] args) {//        List list = new ArrayList();
//        list.add(1);//new Integer
//        list.add("abc");//new String("abc")
//        list.add(true);//new Boolean(true)
//        list.add(new Person("zhangsan",15));
//        System.out.println(list);List<String> list = new ArrayList<String>();list.add("1");//new Integerlist.add("abc");//new String("abc")list.add("true");//new Boolean(true)list.add(new Person("zhangsan",15).toString());//普通for循环for(int i=0;i<list.size();i++){System.out.println(list.get(i));}System.out.println("---------------------");//增强for循环
//        for(Object iter : list){//            System.out.println(iter);
//        }for(String iter : list){System.out.println(iter);}}
}

泛型的高阶运用

1.泛型类

public class FanXingClass<A> {//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);}
}
import java.util.ArrayList;
import java.util.List;
/*泛型的高阶运用1.泛型类在定义类的时候在类名后面添加<E,K,V......>,起到占位的作用,方法类中的方法的返回值和属性的类型都可以使用*/
public class FanXingDemo {public static void main(String[] args) {//1.泛型类FanXingClass<String> fxc = new FanXingClass<String>();fxc.setA("java");fxc.setId(1);fxc.show();FanXingClass<Integer> fxc2 = new FanXingClass<Integer>();fxc2.setA(34);fxc2.setId(2);fxc2.show();FanXingClass<Person> fxc3 = new FanXingClass<Person>();fxc3.setA(new Person("AAA",123));fxc3.setId(3);fxc3.show();}
}

2.泛型接口

第一种实现方式

public interface FanXingInterface<B> {public B test();public void test2(B b);
}
public class FanXingInterfaceSub<B> implements FanXingInterface<B>{//仍不指定子类类型@Overridepublic B test() {return null;}@Overridepublic void test2(B b) {System.out.println(b);}
}
import java.util.ArrayList;
import java.util.List;
/*泛型的高阶运用2.泛型接口在定义接口的时候在类名后面添加<E,K,V......>第一种实现方式:子类在进行实现的时候,可以不填写泛型的类型,此时在创建具体的子类对象的时候才决定使用哪种类型*/
public class FanXingDemo {public static void main(String[] args) {FanXingInterfaceSub<String> fxi = new FanXingInterfaceSub<String>();fxi.test2("abc");}
}

第二种实现

public interface FanXingInterface<B> {public B test();public void test2(B b);
}
public class FanXingInterfaceSub implements FanXingInterface<String>{//直接指定父类类型//实现String方法@Overridepublic String test() {return null;}@Overridepublic void test2(String s) {System.out.println(s);}
}
import java.util.ArrayList;
import java.util.List;
/*子类在实现泛型接口的时候,只在实现父类的接口的时候指定父类的泛型类型此时具体方法中的泛型类型必须要跟父类中的保持一致,也无需声明*/
public class FanXingDemo {public static void main(String[] args) {FanXingInterfaceSub fxi = new FanXingInterfaceSub();//无需用<>声明,此时指定String类型fxi.test2("abc");//abc}
}

3.泛型方法

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);}
}
import java.util.ArrayList;
import java.util.List;
/*泛型方法定义方法的时候,指定方法的返回值和参数是自定义的占位符,可以使类名中的T,也可以是自定义的Q只不过在使用Q的时候,需要把<Q>定义在返回值的前面:public<Q> void show(Q q){System.out.println(q);}*/
public class FanXingDemo {public static void main(String[] args) {FanXingMethod<String> fxm = new FanXingMethod<>();fxm.setT("ttt");fxm.show(123);}
}

4.泛型的上限、反省的下限(基本不会使用)

/*
泛型的上限如果父类确定了,所有的子类可以直接使用
泛型的下限如果子类确定了,子类的所有父类都可以直接传递参数使用
*/

Map

Map基本概念

特点:key-value映射

HashMap

​ Key无序 唯一(Set)

​ Value无序 不唯一(Collection)

LinkedHashMap

​ 有序的HashMap速度快

TreeMap

​ 有序 速度没有hash快

package Map;
/*map存储的是k-v键值对映射的数据实现子类:HashMap:数据+链表(1.7)、数据结构+链表+红黑树(1.8之后)LinkedHashMap:链表TreeMap:红黑树基本api操作:增加:put(k,v):插入查找:isEmpty:判断是否非空size:返回map的大小containsKey:查找kcontainsValue:查找vget:查找对应k的下标删除:clear:清空集合中的所有元素remove:删除指定元素map.entry:表示的是k-v组合的一组映射关系,k-v成组出现*/
import java.util.*;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);System.out.println(map);System.out.println(map.isEmpty());System.out.println(map.size());
//        map.clear();System.out.println(map.containsKey("b"));System.out.println(map.containsValue(4));System.out.println(map.get("a"));//        map.remove("a");System.out.println("---------------------------------------------");//遍历操作 Set<String> keys = map.keySet();for(String key : keys){System.out.println(key+" = "+map.get(key));}Collection<Integer> values = map.values();//只能根据k获取对应的v值,无法用v获取kfor(Integer i : values){System.out.println(i);}System.out.println("---------------------------------------------");//迭代器Set<String> keys2 = map.keySet();Iterator<String> iterator = keys2.iterator();while (iterator.hasNext()){String key = iterator.next();System.out.println(key+" = "+map.get(key));}System.out.println("---------------------------------------------");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());}}
}

hashMap和HashTable的区别

​ 1.hashMap线程不安全,但效率比较高;hashTable线程安全,但效率较低

​ 2.hashMap中的k,v都可以空(null),但hashTable不允许

为什么hashMap初始值为2的N次幂?

​ 1.方便进行操作,提高效率,用“&”进行运算的效率比直接取模要高

​ 2.在扩容之后涉及到元素的迁移过程,迁移的时候只需要判断二进制的前一位是0还是1

​ 如果是0,表示新数组和旧数组的下标位置保持不变;

​ 如果是1,只需要将索引位置加上旧的数组的长度值即为新数组的下标

【面经】HashMap与ConcurrentHashMap在Jdk1.7和1.8的区别

1.HashMap

在jdk1.7之前HashMap是基于数组和链表实现的,而且采用头插法。

而jdk1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。采用尾插法。

HashMap默认的初始化大小为 16。当HashMap中的元素个数之和大于负载因子*当前容量的时候就要进行扩充,容量变为原来的 2 倍。(这里注意不是数组中的个数,而且数组中和链/树中的所有元素个数之和!)

2.ConcurrentHashMap

在jdk1.7是 分段的数组+链表 ,jdk1.8的时候跟HashMap1.8的时候一样都是基于数组+链表/红黑树。

ConcurrentHashMap是线程安全的

(1)在jdk1.7的时候是使用分段所segment,每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。

(2)在jdk1.8的时候摒弃了 Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronizedCAS 来操作。synchronized只锁定当前链表或红黑二叉树的首节点。

Collections工具类

package Collection;
/*Collections工具类addAll:批量添加sort:排序binarySearch:二分查找fill:替换shuffle:随机排序reverse:逆序*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;public class CollectionsDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("aau");list.add("bcuhue");list.add("caoaiw");list.add("dcpcowncwk");Collections.addAll(list, "e","faca","gacscawacavaaw");System.out.println(list);list.sort(new Comparator<String>() {//匿名内部类@Overridepublic int compare(String o1, String o2) {if(o1.length()>o2.length()){return 1;}else if(o1.length()<o2.length()){return -1;}elsereturn 0;}});System.out.println(list);//在使用二分查找的侍候需要先进行排序操作,如果数据是无序的,则找不到指定元素Collections.sort(list);//先排序System.out.println(list);System.out.println(Collections.binarySearch(list, "e"));Collections.reverse(list);System.out.println(list);Collections.fill(list, "java");System.out.println(list);//[java, java, java, java, java, java, java]}
}

Arrays工具类

package Collection;import java.util.Arrays;
import java.util.List;/*Arrays提供了数组操作的工具类,包含很多方法,比较重要的是:集合和数组之间的转化*/
public class ArraysDemo {public static void main(String[] args) {//数组转成listint[] array = new int[]{1,2,3,4};List<int[]> ints = Arrays.asList(array);//转为一个数组元素List<Integer> integers = Arrays.asList(1, 2, 3, 4);//转为单个元素//list转成数组Object[] objects = ints.toArray();}
}

集合总结


【java学习之路】(java SE篇)008.集合相关推荐

  1. 个人开发经历--我的java学习之路(学校篇)

    个人开发经历--我的java学习之路(学校篇) 个人介绍: 姓名: 不在这里说明 联系信息: 个人历程 jdbc阶段 sql生成器 一代代码生成器 servlet阶段 servlet项目中,sql生成 ...

  2. java学习之路---java学习的方法和java学习路线

    转载于: http://blog.csdn.net/zhangerqing 前段时间逛论坛,总会有很多新手很迷茫,问到:到底该怎么学好Java,这个问题很重要,尤其对于像我们这样大多数都是靠自学的人来 ...

  3. Java学习之路-----Java基础简介,基础语法,Java标识符,修饰符,关键字与注释

    这里写目录标题 Java简介 Java发展历程 Java语言平台版本 Java语言的特点 Java语言跨平台原理--JVM JRE和JDK JDK安装路径下的目录解释 Java基础语法 Java标识符 ...

  4. Java学习之路 -- Java怎么学?

    文章目录 java基础怎么学? 学完基础学什么? 几个常用框架学完学什么? MQ JVM的知识跑不掉 微服务等等 其他 数据结构和算法 java基础怎么学? 当时,作为懵懂的小白,大一学习了c和c++ ...

  5. JAVA学习之路--基础篇三

    目录 关于Java中从键盘输入的语句 nextxxx().next().nextLine()的区别 语句 if和if else语句 Switch语句 for语句 while和do..while bre ...

  6. java学习之路目录(已完结)

    java学习之路目录(持续更新中-) 第一阶段 javaSE(完结) 序号 标题 内容 001 java初识 java语言特点.体系结构.运行机制 002 java SE基础语法 注释.关键字.变量. ...

  7. 我的Java学习之路2009-11-17

    -------------------------------2009年3月19日开始----------------------------- 下载JDK Myeclipse Netbeans JB ...

  8. 菜鸟haqima的Java学习之路第一天

    菜鸟haqima的Java学习之路第一天 导读:DOS命令 常用快捷键 Java的简单概述 (第一章 Java开发环境的搭建) 1.常用的DOS命令 1.1.怎么打开DOS命令窗口 win键+r(组合 ...

  9. Java学习之路02_选择方向_旺旺老师

    提示:请您先阅读第一部分:Java学习之路01_软件江湖_旺旺老师 第二部分:帮派之争 就好像玩游戏要先选择角色种族,进入江湖要先选择帮派,那搞软件开发也要选择方向.个人总结的软件开发的方向:嵌入式开 ...

  10. Java学习之路-预科

    Java学习之路-预科 第一章 学习计算机的基本知识 文章目录 Java学习之路-预科 前言 一.什么是计算机? 二.硬件及冯诺依曼结构 1.计算机硬件 1.1 计算机硬件组成 1.2 什么是装机 1 ...

最新文章

  1. 前端传值后端接收不到_web前端和后端哪个好
  2. SD-WAN平台的要素
  3. 注水法比特功率分配介绍及MATLAB实现
  4. mysql 报错ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executin
  5. [Unity] 3D数学基础 - 坐标系、向量、矩阵
  6. bzoj2058: [Usaco2010 Nov]Cow Photographs(逆序对)
  7. TIOBE 11 月榜单:Python 挤掉 Java,Java的下跌趋势确立了?
  8. 重磅!Yolo v4横空出世!刚刚开源!
  9. 静秋姐姐运营课程-笔记
  10. android 代码植入,Android Studio之Debug运行期代码植入的方法
  11. linux uuid挂载磁盘_linux下mount硬盘步骤,含UUID mount办法
  12. 必须声明标量变量是什么意思_机器视觉学习之halcon系列---一文带你理解handle变量是什么意思...
  13. 联想服务器控制口登录地址_联想服务器登录管理界面 联想服务器客服
  14. 计算机论文的研究思路与方法,硕士论文中研究方法怎么写 介绍3种简单的方法...
  15. VMware16安装Win10系统图文教程
  16. 技术管理之巅-如何从零打造高质效互联网技术团队?
  17. OtterCTF 内存取证
  18. Chrome源码剖析——多线程模型、进程通信、进程模型
  19. Mac-Windows下IDEA卡顿问题解决
  20. 快速开放,推荐一个视频通话sdk agora

热门文章

  1. 视频标签- video 音频标签- audio
  2. JS根据分数,计算名次(分数相同名次相同)
  3. Vue脚手架中添加favicon.ico图标失效问题
  4. opencv之retina滤波器---Retina_create
  5. 2018年内蒙古孕产妇、婴儿死亡率实现双下降
  6. 阿里开发者们的第15个感悟:做一款优秀大数据引擎,要找准重点解决的业务场景...
  7. NodeJS + Sequelize + Mysql + Vue + Bootstrap
  8. Android第三十三期 - Dialog的应用
  9. Unity3D的四种坐标系
  10. 用express搭建网站