Java面试知识点:集合、Set、泛型、HashSet、HashMap

答案:

1.集合


集合和数组的对比小结
     1,数组的长度是不可变的,集合的长度是可变的。
     2 ,数组可以存基本数据蟀和引用数据类型。
集合只能存引用数据类型,如野存基本数据类型,需要存对应的包装类。

迭代器小结
• lterator<E> iterator() :创建迭代器对象,默认指向当前集合的0索引。
• boolean hasNext() :判断当前位置是否有元素可以被取出
• E next() :获取当前位置的元素,将迭代器对象移向下一个索引位置
增强for循环
 增强for:简化数组和Collection集合的遍历
 • 它是JDK5之后出现的,其内部原理是一个Iterator迭代器
 •实现Iterable接口的类才可以使用迭代器和增强for

package com.xy;

import java.util.ArrayList;
import java.util.Collection;

/**
 * @ProjectName: day01
 * @Package: com.xy
 * @ClassName: test01
 * @Author: 杨路恒
 * @Description:
 * @Date: 2021/8/18 0018 10:18
 * @Version: 1.0
 */
public class test01 {
    public static void main(String[] args) {
        Collection<String> collection=new ArrayList<>();
        collection.add("杨大大");
        System.out.println(collection);
        collection.add("恒大大");
        collection.remove("恒大大");
        System.out.println(collection);
        collection.removeIf((String s)->{
            return s.length()<=3;
        });
        System.out.println(collection);
    }
}





package com.xy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * @ProjectName: day01
 * @Package: com.xy
 * @ClassName: test02
 * @Author: 杨路恒
 * @Description:
 * @Date: 2021/8/18 0018 15:41
 * @Version: 1.0
 */
public class test02 {
    public static void main(String[] args) {
        Collection<String> collection=new ArrayList<>();
        collection.add("杨大大");
        collection.add("恒大大");
        Iterator<String> iterator=collection.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        for (String s:collection
             ) {
            System.out.println(s);
        }
    }
}





package com.xy;

import java.util.LinkedList;

/**
 * @ProjectName: day01
 * @Package: com.xy
 * @ClassName: test03
 * @Author: 杨路恒
 * @Description:
 * @Date: 2021/8/18 0018 19:18
 * @Version: 1.0
 */
public class test03 {
    public static void main(String[] args) {
        LinkedList<String> linkedList=new LinkedList<>();
        linkedList.add("杨大大");
        linkedList.add("恒大大");
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }
        linkedList.addFirst("杨");
        linkedList.addLast("恒");
        for (String s : linkedList) {
            System.out.println(s);
        }
        System.out.println(linkedList.getFirst());
        System.out.println(linkedList.getLast());
        linkedList.remove(0);
        linkedList.removeFirst();
        linkedList.removeLast();
        for (int i = 0; i <linkedList.size() ; i++) {
            System.out.println(linkedList.get(i));
        }
    }
}

2.Set集合


Set集合概述和特点
Set集合特点
•  可以去除重复
•  存取顺序不一致
•  没有带索引的方法,所以不能使用普通for循环遍历,也不能通过获取索引来获取,删除Set集合里面的元素

Set集合练习
•  存储字符串并遍历

public class test04Set集合{
    public static void main(String[] args) {
        Set<String> strings=new TreeSet<>();
        strings.add("杨大大");
        strings.add("恒大大");
        Iterator<String> iterator = strings.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        for (String string : strings) {
            System.out.println(string);
        }

        TreeSet<Integer> treeSet=new TreeSet<>();
        treeSet.add(1);
        treeSet.add(2);
        treeSet.add(3);
        System.out.println(treeSet);
    }
}

Java 根据集合个数声明变量 java集合长度可变吗_System

Java 根据集合个数声明变量 java集合长度可变吗_Java 根据集合个数声明变量_02

Java 根据集合个数声明变量 java集合长度可变吗_System_03

Java 根据集合个数声明变量 java集合长度可变吗_数组_04

 

代码如下:

public class Student implements Comparable<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='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        int i = this.age - o.age;
        i=i==0?this.name.compareTo(o.name):i;
        return i;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}




public class test05Set集合 {
    public static void main(String[] args) {
        /*TreeSet<Student> treeSet=new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //o1表示现在要存入的那个元素
                //o2表示已经存入到集合中的元素
                int i = o1.getAge() - o2.getAge();  //主要条件
                i=i==0?o1.getName().compareTo(o2.getName()):i;  //次要条件
                return i;
            }
        });*/
        TreeSet<Student> treeSet=new TreeSet<>(
                (Student o1, Student o2)->{
                    int i = o1.getAge() - o2.getAge();  //主要条件
                    i=i==0?o1.getName().compareTo(o2.getName()):i;  //次要条件
                    return i;
                }
        );

        treeSet.add(new Student("杨大大",22));
        treeSet.add(new Student("恒大大",23));
        treeSet.add(new Student("路大大",23));
        System.out.println(treeSet);//不实现implements Comparable<Student>会报Exception in
        // thread "main" java.lang.ClassCastException:
        // com.xy.Student cannot be cast to java.lang.Comparable

    }
}

Java 根据集合个数声明变量 java集合长度可变吗_Java 根据集合个数声明变量_05

3.泛型
(1)泛型概述
泛型:是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型 它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型
这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口

Java 根据集合个数声明变量 java集合长度可变吗_Java 根据集合个数声明变量_06

Java 根据集合个数声明变量 java集合长度可变吗_数组_07

 代码如下:

(1)泛型类:

package com.xy;

public class Generic<T>{
    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}




public class test06泛型 {
    public static void main(String[] args) {
        TreeSet treeSet=new TreeSet();
        treeSet.add("杨大大");
//        treeSet.add(6);

        Generic<String> generic=new Generic<>();
        generic.setT("杨大大");
        Generic<Integer> generic1=new Generic<>();
        generic1.setT(6);
        System.out.println(generic.getT());
        System.out.println(generic1.getT());
        Generic1<Integer> generic11=new Generic1Impl();
        generic11.show(6);
    }
}

 

(2)泛型接口

public interface Generic1<T> {
    void show(T t);
}




public class Generic1Impl implements Generic1 {
    @Override
    public void show(Object o) {

    }
}



public class test06泛型 {
    public static void main(String[] args) {
        TreeSet treeSet=new TreeSet();
        treeSet.add("杨大大");
//        treeSet.add(6);

        Generic<String> generic=new Generic<>();
        generic.setT("杨大大");
        Generic<Integer> generic1=new Generic<>();
        generic1.setT(6);
        System.out.println(generic.getT());
        System.out.println(generic1.getT());
        Generic1<Integer> generic11=new Generic1Impl();
        generic11.show(6);
    }
}

(3)

public class test07泛型 {
    public static void main(String[] args) {
        List<?> list=new ArrayList<Object>();
        List<?> list1=new ArrayList<Number>();
        List<?> list2=new ArrayList<Integer>();
        List<? extends Number> list3=new ArrayList<Number>();
        List<? extends Integer> list4=new ArrayList<Integer>();
        List<? super Number> list5=new ArrayList<Number>();
        List<? super Integer> list6=new ArrayList<Integer>();
    }
}

 4.HashSet
哈希值
哈希值(哈希码值):是JDK根据对象的地址或者属性值,算出来的int类型的整数
Object类中有一个方法可以获取对象的哈希值
• public int hashCode():根据对象的地址值计算出来的哈希值
对象的哈希值特点
• 如果没有重写hashCode方法,那么是根据对象的地址值计算出的哈希值。同一个对象多次调用hashCode()方法返回的哈希值是相同的不同对象的哈希值是不一样的。
• 如果重写了hashCode方法,一般都是通过对象的属性值计算出哈希值。
        如果不同的对象属性值是一样的,那么计算出来的哈希值也是一样的。

HashSet1.7版本原理总结
     • 底层结构:哈希表。(数组+链表)
     • 数组的长度默认为16,加载因子为0.75
     • 首先会先获取元素的哈希值,计算出在数组中应存入的索引
      判断该索引处是否为null
      如果是null ,直接添加
      如果不是null ,则与链表中所有的元素,通过equals方法比较属性值 只要有一个相同,就不存,如果都不一样,才会存入集合。
HashSet1.8版本原理解析
    底层结构:哈希表。(数组、链表、红黑树的结合体)。
    当挂在下面的元素过多,那么不利于添加,也不利于查询,所以在JDK8以后, 当链表长度超过8的时候,自动转换为红黑树。

代码如下:

public class test09HashSet {
    public static void main(String[] args) {
        HashSet<String> hashSet=new HashSet<>();
        hashSet.add("杨大大");
        hashSet.add("恒大大");
        Iterator<String> iterator = hashSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        for (String s : hashSet) {
            System.out.println(s);
        }
    }
}


public class test10HashSet {
    public static void main(String[] args) {
        HashSet<Student> hashSet=new HashSet<>();
        hashSet.add(new Student("杨大大",22));
        hashSet.add(new Student("恒大大",23));
        hashSet.add(new Student("杨大大",22));
        /**
         * 结论:
         *      如果HashSet集合要存储自定义对象,那么必须重写hashCode和equals方法。
         */
        for (Student student : hashSet) {
            System.out.println(student.hashCode());
        }
    }
}

5.HashMap

代码如下:

public class test11HashMap {
    public static void main(String[] args) {
        Map<String,String> map=new HashMap<>();
        map.put("1","杨大大");
        map.put("2","恒大大");
        System.out.println(map);
        System.out.println(map.get("1"));
        System.out.println(map.size());
        Set<String> strings = map.keySet();
        System.out.println(strings);
        Collection<String> values = map.values();
        System.out.println(values);
        for (String s : strings) {
            System.out.println(map.get(s));
        }
    }
}





public class test12HashMap {
    public static void main(String[] args) {
        Map<String,Student> map=new HashMap<>();
        map.put("1",new Student("杨大大",22));
        map.put("2",new Student("恒大大",22));
        Set<String> keySet = map.keySet();
        for (String s : keySet) {
            System.out.println(map.get(s));
        }
        Set<Map.Entry<String, Student>> entries = map.entrySet();
        for (Map.Entry<String, Student> entry : entries) {
            System.out.println(entry);
        }
    }
}





public class test13HashMap {
    public static void main(String[] args) {
        Map<Student,String> map=new HashMap<>();
        map.put(new Student("杨大大",22),"西安");
        map.put(new Student("恒大大",22),"上海");
        Set<Student> keySet = map.keySet();
        for (Student s : keySet) {
            System.out.println(map.get(s));
        }
        Set<Map.Entry<Student, String>> entries = map.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            System.out.println(entry);
        }
        map.put(new Student("恒大大",22),"上海");

    }
}




public class test14HashMap {
    public static void main(String[] args) {
        ArrayList<HashMap<String,String>> array=new ArrayList<>();
        HashMap<String,String> map=new HashMap<>();
        map.put("杨大大","22");
        map.put("恒大大","22");
        HashMap<String,String> map1=new HashMap<>();
        map1.put("杨大大","22");
        map1.put("恒大大","22");
        array.add(map);
        array.add(map1);
        for (HashMap<String, String> hashMap : array) {
            System.out.println(hashMap);
        }

    }
}