Collection

集合的由来:

数组的长度是固定的,当添加的元素超过了数组的长度时,需要对数组重新定义,太麻烦。Java内部给我们提供了集合类,长度是可以改变的。

数组和集合的区别:

区别一:

数组既可以存储基本数据类型,也可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值

集合只能存储引用数据类型(对象)。也可以存储基本数据类型,但在存储的时候会自动装箱变成对象

区别二:

数组长度是固定的,不能自动增长

集合的长度是可变的,可以根据元素个数的变化而变化

使用时机:

元素个数固定推荐使用数组

元素个数不是固定推荐使用集合

集合继承体系图

java 什么集合key可以重复 java集合长度可变吗_java 什么集合key可以重复


主要方法

java 什么集合key可以重复 java集合长度可变吗_java_02


Iterator

java 什么集合key可以重复 java集合长度可变吗_List_03

public class Test {

    public static void main(String[] args) {
        Collection<Person> c = new ArrayList<Person>();

        c.add(new Person(1, "John", "12"));
        c.add(new Person(2, "Tom", "34"));
        c.add(new Person(3, "Mick", "45"));
        c.add(new Person(4, "Jack", "56"));
        System.out.println(c);
        System.out.println("--------------------------------");
        Iterator<Person> it = c.iterator();
        while (it.hasNext()) {
//            System.out.println(it.next());
            Person person = (Person) it.next();
            System.out.println(person.getAge()+" "+person.getId()+" "+person.getName());
        }

    }
}

迭代器原理:
迭代器是对集合进行遍历,而每一个集合内部的存储结构是不同的,所以每一个集合存和取都是不一样的那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器将这样的方法向上抽取出接口,然后在每一个类的内部,定义自己的迭代方法,这样做的好处有二个:第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二代码由底层内部实现,使用者不需要关心如何实现,会用即可

List集合

java 什么集合key可以重复 java集合长度可变吗_java 什么集合key可以重复_04


java 什么集合key可以重复 java集合长度可变吗_java 什么集合key可以重复_05


注意一:删除时不会自动装箱,remove()方法里面写索引

java 什么集合key可以重复 java集合长度可变吗_Map_06


java 什么集合key可以重复 java集合长度可变吗_Map_07


注意二:使用迭代器的时候再进行增删操作会导致并发异常

java 什么集合key可以重复 java集合长度可变吗_java_08


List中特有的ListIterator可以解决这个问题

java 什么集合key可以重复 java集合长度可变吗_Set_09


vector特有的添加和迭代方式

public class Test03 {
    public static void main(String[] args) {
        Vector<String> vector = new Vector<String>();
//        vector.add("a");
//        vector.add("b");
//        vector.add("c");
//        vector.add("d");
//        System.out.println(vector);
        vector.addElement("a");
        vector.addElement("b");
        vector.addElement("c");
        vector.addElement("d");

        Enumeration<String> v = vector.elements();//获取枚举
        while (v.hasMoreElements()) {//判断集合中是否有元素
            System.out.println(v.nextElement());//获取集合中的元素
        }

    }
}

数组和链表区别:
数组:查询快,修改也快,增删慢
链表:查询慢,修改也慢,增删快
List三个子类的特点
ArrayList:
底层数组实现,查询快,增删慢。线程不安全,效率高
Vector:
底层数组实现,查询快,增删慢,线程安全,效率低
LinkedList:
底层链表实现,查询慢,增删快,线程不安全,效率高

Vector相对ArrayList查询慢(线程安全)
Vector相对LinkedList增删慢

Vector和ArrayList区别:
vector是线程安全的,效率低
ArrayList是线程不安全的,效率高

ArrayList和LinkedList的区别:
ArrayList底层是数组结构,查询和修改快
LinkedList底层是链表结构,增删比较快

使用时机:
查询多用ArrayList
增删多用LinkedList
都多用ArrayList

例题:去重(通过ArrayList实现)
思路:创建一个新的ArrayList集合,判断是否包含,不包含就加入

public class Test04 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("a");
        list.add("b");
        list.add("d");
        list.add("e");
        list.add("a");
        ArrayList<String> list2 = new ArrayList<String>();
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            if(!list2.contains(o)){
                list2.add((String) o);
            }
        }
        System.out.println("list:"+list);
        System.out.println("list2:"+list2);
    }
}

注意:如果是对象,需要重写equals方法
原因:contains方法判断是否包含底层依赖的是equals方法
remove方法判断是否删除,底层依赖的也是equals方法

public class Test05 {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<Person>();
        list.add(new Person(1,"John","23"));
        list.add(new Person(1,"John","23"));
        list.add(new Person(2,"Tom","33"));
        list.add(new Person(3,"Jack","44"));
        list.add(new Person(4,"John","23"));
        list.add(new Person(4,"Mick","23"));

            ArrayList<Person> list2 = new ArrayList<Person>();
        Iterator<Person> it = list.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            if(!list2.contains(o)){
                list2.add((Person) o);
            }
        }
        System.out.println("list:"+list);
        System.out.println("list2:"+list2);
    }
}
package com.itany.day01;

import java.util.Objects;

/**
 * Author: zhh
 * Date: 2022-10-03 15:58
 * Description: <描述>
 */
public class Person {
    private Integer id;
    private String name;
    private String age;


    public Person() {
    }

    public Person(Integer id, String name, String age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return id
     */
    public Integer getId() {
        return id;
    }

    /**
     * 设置
     * @param id
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public String getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(String age) {
        this.age = age;
    }

    public String toString() {
        return "Person{id = " + id + ", name = " + name + ", 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 Objects.equals(id, person.id) &&
                Objects.equals(name, person.name) &&
                Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, age);
    }
}

LinkedList

java 什么集合key可以重复 java集合长度可变吗_List_10


java 什么集合key可以重复 java集合长度可变吗_List_11


java 什么集合key可以重复 java集合长度可变吗_java 什么集合key可以重复_12


用LinkedList模拟简单栈结构

public class Stack {
    private LinkedList list=new LinkedList();

    /**
     * 模拟进栈
     */
    public void in(Object obj) {
        list.addLast(obj);
    }

    /**
     * 模拟出栈
     */
    public void out(Object obj) {
        list.removeLast();
    }

    /**
     * 模拟栈是否为空
     */
    public boolean isEmpty() {
        return list.isEmpty();
    }
}

泛型
好处:提高安全性(将运行时的错误转换到编译期)、省去强转的麻烦
基本使用:<>中放的必须是引用数据类型
注意事项:前后泛型必须一致,或者后面的泛型可以省略不写

增强for
简化数组和Collection集合遍历
格式:for(元素数据类型 变量:数组或者Collection集合){使用变量即可}

三种迭代能否删除

  • 普通for循环,可以删除,但是索引要–(可以反过来)
  • 迭代器:可以删除,但是必须使用迭代器自身的remove方法,否则会发生并发修改异常
  • 增强for循环:不可以删除

数组转集合
注意基本数据类型的数组转换成集合,会将整个数组当成一个对象转换
将数组转换成集合,数组必须是引用数据类型

public class Test07 {

    public static void main(String[] args) {
        //注意基本数据类型的数组转换成集合,会将整个数组当成一个对象转换
        //将数组转换成集合,数组必须是引用数据类型
//        int[] arr={11,22,33,44,55};
//        List<int[]>list = Arrays.asList(arr);
//        System.out.println(list);//结果[[I@1b6d3586]
        Integer[] arr={11,22,23,24,25,26,27,28,29};
        List<Integer> list = Arrays.asList(arr);
        System.out.println(list);//结果[11, 22, 23, 24, 25, 26, 27, 28, 29]

    }
}

集合转数组
注意:当数组长度小于集合的size时,转换后的数组长度等于集合的size
当数组的长度大于等于集合的size时,转换后的数组长度和指定的数组长度一样

public class Test08 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
//        String[] arr=list.toArray(new String[10]);
//        System.out.println(arr.length);//10
        String[] arr=list.toArray(new String[2]);
        for (String s:arr){
            System.out.println(s);
        }
        System.out.println(arr.length);//4
    }
}

Set集合

HashSet

java 什么集合key可以重复 java集合长度可变吗_List_13

public class Test09 {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<String>();
        boolean b1 = set.add("a");
        boolean b2 = set.add("b");
        boolean b3 = set.add("b");//重复添加返回true
//        System.out.println(set);
        System.out.println(b1);//true
        System.out.println(b2);//true
        System.out.println(b3);//false
        for(String s:set){//能用迭代器迭代的就能使用增强for循环遍历
            System.out.println(s);
        }
    }
}

注意:添加对象需要重写equals()和hashCode()方法

public class Test10 {
    public static void main(String[] args) {
        HashSet<Person> set = new HashSet<Person>();
        set.add(new Person(1, "John", "23"));
        set.add(new Person(2, "John", "55"));
        set.add(new Person(3, "John", "23"));
        set.add(new Person(1, "John", "23"));

        for(Person person :set) {
            System.out.println(person);
        }
        //未重写equals和hashCode结果
//Person{id = 3, name = John, age = 23}
//Person{id = 2, name = John, age = 55}
//Person{id = 1, name = John, age = 23}
//Person{id = 1, name = John, age = 23}
        //重写equals和hashCode结果
//Person{id = 1, name = John, age = 23}
//Person{id = 2, name = John, age = 55}
//Person{id = 3, name = John, age = 23}
    }
}

HashSet原理:
我们使用Set集合是需要去重复的,如果在存储的时候逐个比较equals,效率较低,哈希算法提高了去重复的效率,降低了使用equals方法的次数

  • 当HashSet调用add方法存储对象的时候,先调用对象的hashCode()方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象
  • 如果没有哈希值相同的对象,直接放入集合中
  • 如果有哈希值相同的对象,就和哈希值相同的对象进行equals比较,比较结果为false就存入,比较结果为true则不存

将自定义的对象存入HashSet去重复

  • 类中必须重写equals()和hashCode()方法
  • hashCode():属性相同的对象必须返回值必须相同,属性不同的对象返回值尽可能不同(提高效率)
  • equals():属性相同返回true,属性不同返回false,返回false时存储

LinkedHsahSet

  • LinkedHashSet底层是链表实现的,是set中唯一一个能保证怎么存就怎么取的集合对象
  • 因为是HashSet的子类,所以也保证元素的唯一,与HashSet的原理一样

java 什么集合key可以重复 java集合长度可变吗_java_14

public class Test11 {
    public static void main(String[] args) {
        LinkedHashSet<String> st = new LinkedHashSet<>();
        st.add("c");
        st.add("d");
        st.add("e");
        st.add("a");
        st.add("b");
        st.add("b");
        st.add("c");
        st.add("d");
        st.add("e");
        st.add("e");

        for(String s :st){
            System.out.println(s);
        }
//结果
//c
//d
//e
//a
//b
    }
}

例题1:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并把最终的随机数输出到控制台

public class Test12 {
    public static void main(String[] args) {
        Random rand = new Random();
        HashSet<Integer> hs = new HashSet<Integer>();
        while(hs.size()<10){
            hs.add(rand.nextInt(20)+1);
        }
        for(Integer h : hs){
            System.out.print(h+" ");
        }
    }
}

例题2:去除字符串中的重复字符

public class Test13 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str = scanner.nextLine();
        char[] ch =  str.toCharArray();
        HashSet<Character> chSet = new HashSet<Character>();
        for(int i=0;i<ch.length;i++){
           chSet.add(ch[i]);
        }
        for(char chs : chSet){
            System.out.print(chs);
        }
    }
}

例题3:去除List集合中的重复元素

public class Test14 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("e");
        list.add("f");
        list.add("b");
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");

        LinkedHashSet<String> lhs = new LinkedHashSet<String>(list);
        list.clear();
        list.addAll(lhs);
        for (String li:list) {
            System.out.print(li+" ");//a e f b c d 
        }
    }
}

TreeSet

java 什么集合key可以重复 java集合长度可变吗_List_15

java 什么集合key可以重复 java集合长度可变吗_List_16


java 什么集合key可以重复 java集合长度可变吗_java 什么集合key可以重复_17

  • TreeSet集合是用来对对象元素进行排序的,同样他也可以保证元素的唯一
public class Test15 {
    public static void main(String[] args) {
        TreeSet<Integer> ts=new TreeSet<Integer>();
        ts.add(2);
        ts.add(5);
        ts.add(9);
        ts.add(1);
        ts.add(3);
        ts.add(2);
        System.out.println(ts);//[1, 2, 3, 5, 9]
    }
}

注意:存对象时需要让它继承comparable接口,并重写compareTo方法

  • 当compareTo方法返回0的时候,集合中只有一个元素
  • 当compareTo方法返回正数的时候,集合会怎么存就怎么取
  • 当compareTo方法返回负数的时候,集合会倒序存取
public class Test16 {
    public static void main(String[] args) {
        TreeSet<Person> ts = new TreeSet<Person>();
        ts.add(new Person(1,"zjj","34"));
        ts.add(new Person(2,"jack","22"));
        ts.add(new Person(3,"zhh","25"));
        ts.add(new Person(4,"zj","34"));
        ts.add(new Person(4,"zj","34"));
        System.out.println(ts);//返回0//[Person{id = 1, name = zjj, age = 34}]
        System.out.println(ts);//返回1
        //[Person{id = 1, name = zjj, age = 34}, Person{id = 2, name = jack, age = 22}, Person{id = 3, name = zhh, age = 25}, Person{id = 4, name = zj, age = 34}, Person{id = 4, name = zj, age = 34}]
        System.out.println(ts);//返回-1
//        [Person{id = 4, name = zj, age = 34}, Person{id = 4, name = zj, age = 34}, Person{id = 3, name = zhh, age = 25}, Person{id = 2, name = jack, age = 22}, Person{id = 1, name = zjj, age = 34}]
    }
}

原理:
二叉树:两个叉
小的存储在左边(负数),大的存储在右边(正数),相等就不存(0)
在TreeSet集合中如何存储元素取决于compareTo方法的返回值

重写compareTo方法示例:

//    @Override
//    public int compareTo(Person o) {
//        int num=this.age.compareTo(o.getAge());//年龄是比较的主要条件
//        return num == 0 ? this.name.compareTo(o.getName()):num;//姓名是比较的次要条件
//    }

//    @Override
//    public int compareTo(Person o) {
//        int num=this.id-o.getId();
//        //id是比较的主要条件
//        return num == 0 ? this.age.compareTo(o.getAge()):num;
//        //年龄是比较的次要条件
//    }
        @Override
        public int compareTo(Person o) {
            int oid=this.id-o.getId();
            //id是比较的主要条件
            int num=oid==0?this.name.compareTo(o.getName()) : oid;
            //姓名是比较的第二条件
            return num == 0 ? this.age.compareTo(o.getAge()):num;
            //年龄是比较的次要条件
        }

//    @Override
//    public int compareTo(Person o) {
//        return -1;
//    }

怎样决定排序方式:
1、自然顺序(Comparable)

  • TreeSet类的add方法中会把存入的对象提升为Comparable类型
  • 调用compareTo方法和集合中的对象比较
  • 根据compareTo方法放回的结果进行存储

2、比较器顺序(Comparator)

  • 创建TreeSet的时候可以制定一个比较器(Comparator)
  • 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器的顺序进行排序
  • add方法内部会自动调用Comparator接口中的compare方法进行排序

3、两种方式的区别

  • TreeSet构造函数什么都不传,默认按照类中的Comparable的顺序(没有就报错)
  • TreeSet如果传入Comparator,就优先按照Comparator
public class Test18 {
    public static void main(String[] args) {
//        TreeSet<Person> ts=new TreeSet<Person>(new CompareByParam());
        TreeSet<Person> ts=new TreeSet<Person>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int oid=o1.getAge().compareTo(o2.getAge());
                //年龄是比较的主要条件
                int num=oid==0?o1.getName().compareTo(o2.getName()) : oid;
                //姓名是比较的第二条件
                return num == 0 ? o1.getId().compareTo(o2.getId()):num;
                //id是比较的次要条件
            }
        });
        ts.add(new Person(1, "张飞", "28"));
        ts.add(new Person(3, "李白", "22"));
        ts.add(new Person(5, "后羿", "28"));
        ts.add(new Person(2, "百里守约", "40"));
        System.out.println(ts);
    }

    //不写内部类想多次使用可以在这边写一个
//    static class CompareByParam implements Comparator<Person>{
//
//        @Override
//        public int compare(Person o1, Person o2) {
//            int oid=o1.getAge().compareTo(o2.getAge());
//            //年龄是比较的主要条件
//            int num=oid==0?o1.getName().compareTo(o2.getName()) : oid;
//            //姓名是比较的第二条件
//            return num == 0 ? o1.getId().compareTo(o2.getId()):num;
//            //id是比较的次要条件
//        }
//    }

}

例题1:在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且不能去除重复

public class Test19 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("d");
        list.add("d");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("c");
        list.add("c");
        list.add("b");
        list.add("b");
        list.add("a");
        sort(list);
        System.out.println(list);//[a, a, b, b, b, b, c, c, c, d, d]
    }
    public static void sort(List<String> list){
        TreeSet<String> ts=new TreeSet<String>(new Comparator<String>(){
            @Override
            public int compare(String o1, String o2) {
                int num=o1.compareTo(o2);
                return num==0?1:num;
            }
        });
        ts.addAll(list);
        
        list.clear();
        list.addAll(ts);
    }
}

Map接口

java 什么集合key可以重复 java集合长度可变吗_java_18


Map接口和Collection接口的不同

  • Map接口是双列的,Collection接口是单列的
  • Map的键唯一,Collection的子体系Set是唯一的
  • Map集合的数据结构只针对键有效,跟值无关,Collection集合的数据结构是针对元素有效
  • 双列集合没有迭代器Iterator

    put方法
public class Test20 {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        Integer i1=map.put("zhh",1);
        Integer i2=map.put("zh",3);
        Integer i3=map.put("zjh",5);
        Integer i4=map.put("zhj",7);
        Integer i5=map.put("zzj",9);
        Integer i6=map.put("zhh",3);
        System.out.println(map);
        System.out.println(i1);
        System.out.println(i2);
        System.out.println(i3);
        System.out.println(i4);
        System.out.println(i5);
        System.out.println(i6);
//结果
//{zjh=5, zhh=3, zzj=9, zhj=7, zh=3}
//null
//null
//null
//null
//null
//1
    }
}

remove方法

public class Test21 {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        Integer i1=map.put("zhh",1);
        Integer i2=map.put("zh",3);
        Integer i3=map.put("zjh",5);
        Integer i4=map.put("zhj",7);
        Integer i5=map.put("zzj",9);
        Integer i6=map.put("zhh",3);
        Integer ii1=map.remove("zhj");
        Integer ii2=map.remove("zjjj");
        System.out.println(map);
        System.out.println(ii1);
        System.out.println(ii2);
//结果
//        {zjh=5, zhh=3, zzj=9, zh=3}
//        7
//        null
    }
}

containsKey和containsValue和isEmpty方法

public class Test22 {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        Integer i1=map.put("zhh",1);
        Integer i2=map.put("zh",3);
        Integer i3=map.put("zjh",5);
        Boolean b1=map.containsKey("zhh");
        Boolean b2=map.containsKey("zhhh");
        Boolean b3=map.containsValue(1);
        Boolean b4=map.containsValue(6);
        Boolean b5=map.isEmpty();
        System.out.println(map);
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);
        System.out.println(b4);
        System.out.println(b5);
//结果
//        {zjh=5, zhh=1, zh=3}
//true
//false
//true
//false
//false
    }
}

map.keySet()和map.get(key)方法

public class Test23 {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        Integer i1=map.put("zhh",1);
        Integer i2=map.put("zh",3);
        Integer i3=map.put("zjh",5);

        Integer value1=map.get("zhh");//根据键获取值
        Integer value2=map.get("zhhh");//根据键获取值

        System.out.println(map);
        System.out.println(value1);//1
        System.out.println(value2);//null

        Set<String> keySet = map.keySet();//获取所有键的集合
        Iterator<String> it = keySet.iterator();//获取迭代器
        while(it.hasNext()) {
            String key = it.next();
            Integer value = map.get(key);//根据key获取值
            System.out.println(key + "=" + value);
//              zjh=5
//              zhh=1
//              zh=3
        }

        //增强for循环简化
        for(String key : map.keySet()) {
            System.out.println(key + "=" + map.get(key));
        }
    }
}

Map.entrySet()

java 什么集合key可以重复 java集合长度可变吗_java_19

public class Test24 {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        Integer i1=map.put("zhh",1);
        Integer i2=map.put("zh",3);
        Integer i3=map.put("zjh",5);

        System.out.println(map);
        Set<Map.Entry<String,Integer>> EntrySet = map.entrySet();
        for(Map.Entry<String,Integer> entry : EntrySet){
            System.out.println(entry.getKey()+"="+entry.getValue());
        }
    }
}

LinkedHashMap

底层是链表实现的,可以保证怎么存就怎么取

java 什么集合key可以重复 java集合长度可变吗_List_20

TreeMap

java 什么集合key可以重复 java集合长度可变吗_List_21


java 什么集合key可以重复 java集合长度可变吗_Set_22


java 什么集合key可以重复 java集合长度可变吗_Set_23


java 什么集合key可以重复 java集合长度可变吗_java_24

public class Test25 {
    public static void main(String[] args) {
        TreeMap<Person,String> treeMap=new TreeMap<Person,String>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int oid=o1.getAge().compareTo(o2.getAge());
                //年龄是比较的主要条件
                int num=oid==0?o1.getName().compareTo(o2.getName()) : oid;
                //姓名是比较的第二条件
                return num == 0 ? o1.getId().compareTo(o2.getId()):num;
                //id是比较的次要条件
            }
        });
        treeMap.put(new Person(1, "zhh","33"), "江苏");
        treeMap.put(new Person(3, "zjj","58"), "南京");
        treeMap.put(new Person(6, "abc","44"), "江苏");
        treeMap.put(new Person(3, "jig","33"), "北京");

        System.out.println(treeMap);
    }

例题1:统计字符串中每个字符出现的次数

public class Test26 {
    public static void main(String[] args) {
        String ss="abcdefgaaaaahhhhgggccc";
        char[] c=ss.toCharArray();
        HashMap<Character,Integer> hashMap=new HashMap<Character,Integer>();
//        for(int i=0;i<c.length;i++){
//            if(hashMap.containsKey(c[i])){
//                hashMap.put(c[i],hashMap.get(c[i])+1);
//            }else{
//                hashMap.put(c[i],1);
//            }
//        }
        //简化写法
        for(char cx :c){
            hashMap.put(cx,!hashMap.containsKey(cx)?1:hashMap.get(cx)+1);
        }
        System.out.println(hashMap);
    }
}

HashTable

java 什么集合key可以重复 java集合长度可变吗_Map_25


java 什么集合key可以重复 java集合长度可变吗_Map_26


HashMap和HashTable区别:

共同点:

  • 底层都是哈希算法,都是双列集合

区别:

  • HashMap是线程不安全的,效率高,JDK1.2版本
  • HashTable是线程安全的,效率低,JDK1.0版本
  • HashMap可以存储null键和null值
  • HashTable不可以存储null键和null值
public class Test27 {
    public static void main(String[] args) {
        HashMap<String,Integer> hashMap = new HashMap<String,Integer>();
        hashMap.put("a",null);
        hashMap.put("c",null);
        hashMap.put("b",null);
        hashMap.put("null",null);
        hashMap.put("null",1);
        System.out.println(hashMap);//{a=null, b=null, c=null, null=1}
    }
}

HashTable键和值都不能为null,有任何一个就会报java.lang.NullPointerException

java 什么集合key可以重复 java集合长度可变吗_List_27

Collections工具类

java 什么集合key可以重复 java集合长度可变吗_List_28


java 什么集合key可以重复 java集合长度可变吗_java_29


java 什么集合key可以重复 java集合长度可变吗_java_30


java 什么集合key可以重复 java集合长度可变吗_java 什么集合key可以重复_31


常用方法示例

sort

public class Test29 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("c");
        list.add("a");
        list.add("a");
        list.add("d");
        list.add("b");
        System.out.println("list: " + list);//list: [c, a, a, d, b]
        Collections.sort(list);
        System.out.println("list排序后: " + list);//list排序后: [a, a, b, c, d]
    }
}

binarySearch

public class Test30 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("a");
        list.add("c");
        list.add("d");
        list.add("g");
        list.add("h");
        System.out.println(Collections.binarySearch(list,"c"));//1
        System.out.println(Collections.binarySearch(list,"b"));//-2//没有返回(-插入点-1)
    }
}

max、reverse、shuffle

public class Test31 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("a");
        list.add("c");
        list.add("d");
        list.add("h");
        list.add("g");
        System.out.println("反转前:"+list);//反转前:[a, c, d, h, g]
        System.out.println(Collections.max(list));//h
        Collections.reverse(list);
        System.out.println("反转后:"+list);//反转后:[g, h, d, c, a]
        Collections.shuffle(list);
        System.out.println("随机置换后:"+list);//随机置换后:[d, a, g, c, h]
        Collections.shuffle(list);
        System.out.println("随机置换后:"+list);//随机置换后:[d, g, a, c, h]
        Collections.shuffle(list);
        System.out.println("随机置换后:"+list);//随机置换后:[d, g, a, h, c]
        
    }
}