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