Java集合框架掏心掏肺式介绍附带面试题(吊打面试官)

Java集合框架

集合框架被设计成要满足以下几个目标。

  • 该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。

  • 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。

  • 对一个集合的扩展和适应必须是简单的。
    在这里插入图片描述
    在这里插入图片描述

从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue(这个现在基本被淘汰),再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。


集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:

  • 接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象

  • 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。

  • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

除了集合,该框架也定义了几个 Map 接口和类。Map 里存储的是键/值对。尽管 Map 不是集合,但是它们完全整合在集合中。

在这里插入图片描述

Collection接口

Collection 层次结构中的根接口,所有的子接口和实现类都会具有他的功能

  • Collection接口的方法 : 添加
    • add (存储元素) 元素存储到集合中
    • addAll (Collection c)将一个集合的元素,添加到另一个集合
  • Collection接口的方法 : 移除
    • boolean remove(元素) 移除集合中指定的元素
    • removeAll(Collection c) ) 移除两个集合中相同元素
  • Collection接口的方法 : 包含
    • boolean contains(元素) 判断元素是否包含在集合中
    • boolean containsAll(Collection c) 判断一个集合中的元素是否完全包含在另一个集合中
  • Collection接口的方法 : 其他
  • int size() 返回集合的长度,就是集合中元素的个数
    • Java中的长度三种表示 : 数组.length 属性 , 字符串.length() 方法, 集合.size()方法
  • void clear() 清空集合中的所有元素, 集合容器本身依然可以使用
  • boolean isEmpty() 判断集合中是否有元素,集合的长度是0,方法返回true
  • Object[] toArray() 集合中的元素转成数组
  • retainAll(Collection c) 两个集合取交集

Collections工具类

java.util.Collections 集合操作的工具类,提供方法来操作集合,方法全部是静态方法

方法 :

  • static void shuffle(List list) 集合元素随机排列
  • static void sort(List list) 集合中元素的自然顺序排序
  • static void sort(List list,Comparator c) 比较器的顺序进行排序
  • static 传递什么返回什么 synchronized开头(传递集合) 线程不安全集合,变成安全的集合
    • Comparator 是比较器接口, 自定义实现类,重写方法
public static void main(String[] args) {
		List<Person> list = new ArrayList<Person>();
		list.add(new Person("a",10));
		list.add(new Person("b",9));
		list.add(new Person("b",12));
		list.add(new Person("b",11));
		list.add(new Person("b",10));
		System.out.println(list);
		//static void sort(List list,Comparator c) 比较器的顺序进行排序 
		Collections.sort(list, new Comparator<Person>() {
			public int compare(Person p1,Person p2) {
				
				return p1.getAge() - p2.getAge();
			}
		});
		
		System.out.println(list);
	}
}
//接口的实现类,重写方法,泛型<T> 写要比较对象
class MyComparator implements Comparator<Person>{
	//方法的参数是两个对象, 参数比较的对象
	public int compare(Person p1,Person p2) {
		//System.out.println(p1.getAge() - p2.getAge());
		return p1.getAge() - p2.getAge();
	}
}

在这里插入图片描述

迭代器 Iterator

迭代器是集合的遍历方式, 迭代器是所有的Collection集合的通用遍历方式.

接口 : java.util.Iterator 迭代器对象

  • Iterator接口的方法
    • boolean hasNext() 判断集合中是否有下一个元素,如果有返回true
    • E next() 取出集合中的下一个元素
    • void remove() 移除元素,遍历到哪个元素,删除哪个元素
  • Iterator接口的实现类
    • 接口实现类的对象,是获取来的,不是我们new的
    • Collection接口中定义方法 : iterator() 作用获取迭代器接口 Iterator的实现类对象
    • Collection col = new ArrayList(); Collection接口中有方法 iterator(),ArrayList重写
      • 对象 col.iterator() 拿到迭代器接口的实现类对象
public static void main(String[] args) {
		//创建集合
		Collection<String> coll = new ArrayList<String>();
		//存储元素
		coll.add("hello");
		coll.add("World");
		coll.add("my");
		coll.add("java");
		
		//1. 获取迭代器接口Iterator的实现类对象
		  //集合对象的方法 iterator()
		Iterator<String> it =  coll.iterator();
		//2. 迭代器对象的方法 hasNext() 判断是否有元素
		//boolean b = it.hasNext();
		//System.out.println(b);
		//3. 迭代器对象的方法 next() 取出元素
		//String str = it.next();
		//System.out.println(str);
		
		//循环中,反复调用方法 hasNext()
		while ( it.hasNext() ) {
			//取出元素
			String str = it.next();
			System.out.println(str);
		}
	}

增强for循环

增强型的for循环,出现在JDK1.5版本.

java.lang.Iterable 接口 实现这个接口允许对象成为 “foreach” 语句的目标。 含数组

谁是接口的实现类 : Collection继承接口Iterable

格式 :

for(数据类型 变量名 : 集合或者数组){
}

好处 : 减少代码量

弊端 : 无索引,不能修改容器中的元素内容

遍历数组

public static void array() {
    int[] arr = {1,3,5,7,9};
    for(int i : arr) {
    	System.out.println(i+1);
    }
    System.out.println(arr[0]);
}

遍历集合

public static void list() {
		List<String> list = new ArrayList<String>();
		list.add("how");
		list.add("do");
		list.add("you");
		list.add("do");
		for(String s : list) {
			System.out.println(s);
		}
		System.out.println("==========");
		
		List<Person> listPerson = new ArrayList<Person>();
		listPerson.add(new Person("a1",101));
		listPerson.add(new Person("a2",102));
		listPerson.add(new Person("a3",103));
		listPerson.add(new Person("a4",104));
		for(Person p : listPerson) {
			System.out.println(p);
		}
	}

增强for循环是个假象

属于编译特效 : javac搞事情

for遍历数组 : javac 编译为传统for形式

for遍历集合 : javac 编译为迭代器


Set集合

java.util.Set 接口, 继承父接口Collection

Set集合特点:

  • 不包含重复元素
  • 没有索引
  • 无序

Set接口方法

Set接口的方法和父接口Collection方法,完全一样

public static void main(String[] args) {
		//Set接口和实现类HashSet创建对象
		Set<String> set = new HashSet<String>();
		set.add("abc");
		set.add("how");
		set.add("are");
		set.add("you");
		//迭代器遍历
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String str = it.next();
			System.out.println(str);
		}
		System.out.println("======");
		//增强for循环遍历
		for(String str : set) {
			System.out.println(str);
		}
	}

Set接口实现类HashSet

java.util.HashSet 类,实现接口Set

HashSet集合特点:

  • 底层数据结构是哈希表
  • 是由HashMap支持的
  • HashSet集合,所有功能,都是由HashMap提供
  • 无序的集合, 元素存储的顺序和取出的顺序不一致
  • 线程不安全集合,运行速度快
public static void main(String[] args) {
    //Set接口和实现类HashSet创建对象
    Set<String> set = new HashSet<String>();
    set.add("d");
    set.add("c");
    set.add("a");
    set.add("b");
    System.out.println(set);
}

LinkedHashSet用法

LinkedHashSet继承自HashSet,源码更少、更简单,唯一的区别是LinkedHashSet内部使用的是LinkHashMap。这样做的意义或者好处就是LinkedHashSet中的元素顺序是可以保证的,也就是说遍历序和插入序是一致的。

package HomeWork;

import java.util.LinkedHashSet;
import java.util.Scanner;

public class Demo3 {
	public static void main(String[] args) {
		System.out.println("输入一个字符串:");
		Scanner scanner = new Scanner(System.in);
		String string = scanner.next();
		
		LinkedHashSet<Character> linkedHashSet = new LinkedHashSet<>();
		
		//把字符串变成单个字母的数组
		char[] arr = string.toCharArray();
		 //集合里插入元素
		for(char b:arr) {
			 linkedHashSet.add(b);
		 }
		 //遍历排序后的数组
		 for(Character b:linkedHashSet) {
			 System.out.print(b);
		 }
	}
}

输入:aabbcc
输出结果为:abc

HashSet去除重复元素的原理

Set接口创建引用型对象是会创建他的实现类HashSet,在储存对象是,集合会调用方法hashCode()
计算出储存元素的哈希值,根据哈希值确定其存储位置,在储存位置上如果已经有元素,就会让后来的对象
调用方法equals()传递先来的对象,两个对象哈希值相同,equals方法返回true,判断为相同元素,就不在储存后来的元素
这就是HashSet去除重复元素的原理。


List接口

java.util. List 接口继承Collection接口

接口的特点

  • 有序, 元素在集合中,存储和取出的顺序一致
  • 允许存储重复元素的集合
  • 该接口中都是带有索引的

接口方法

带有索引的方法学习

  • add(int index,存储元素) 将元素,存储到指定的索引上
  • 元素 get(int index) 返回指定索引上的元素
  • 元素 remove(int index) 移除指定索引上的元素,返回被删除之前的元素
  • 元素 set(int index ,修改的元素) 修改指定索引上的元素,返回被修改之前的
  • List subList(int begin,int end) 截取集合的一部分,包含开始索引,不包含结尾索引
public static void main(String[] args) {
		mySubList();
	}
	/*
	 * subList(int begin, int end)
	 */
	public static void mySubList() {
		//接口多态,创建对象
		List<String> list = new ArrayList<String>();
		//集合存储元素
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		list.add("e");
		list.add("f");
		System.out.println(list);
		//截取集合的元素
		List<String> newList = list.subList(1, 4);
		System.out.println(newList);
	}
	
	/*
	 * set(int index ,要修改的元素)
	 */
	public static void mySet() {
		//接口多态,创建对象
		List<String> list = new ArrayList<String>();
		//集合存储元素
		list.add("a");
		list.add("b");
		list.add("c");
		System.out.println(list);	
		//修改2索引上的元素, 大写C
		String str = list.set(2, "C");
		System.out.println(list);
		System.out.println(str);
	}
	
	/*
	 * remove(int index)
	 */
	public static void myRemove() {
		//接口多态,创建对象
		List<String> list = new ArrayList<String>();
		//集合存储元素
		list.add("a");
		list.add("b");
		list.add("c");
		System.out.println(list);
		//移除1索引上的元素
		String str = list.remove(1);
		System.out.println(list);
		System.out.println(str);
	}
	
	/*
	 * get(int index)
	 */
	public static void myGet() {
		//接口多态,创建对象
		List<String> list = new ArrayList<String>();
		//集合存储元素
		list.add("a");
		list.add("b");
		list.add("c");
		System.out.println(list);
		//获取指定索引上的元素
		String str = list.get(0);
		System.out.println(str);
	}
	
	/*
	 * add(int index , 存储元素)
	 */
	public static void myAdd() {
		//接口多态,创建对象
		List<String> list = new ArrayList<String>();
		//集合存储元素
		list.add("a");
		list.add("b");
		list.add("c");
		System.out.println(list);
		//在指定的索引上添加元素
		list.add(2, "d");
		System.out.println(list);
	}

ArrayList集合

java.util.ArrayList 集合,类实现了接口List (有序,索引,重复)

ArrayList集合,底层是采用数组结构实现,大小可变数组 (复制)

查询速度快,增删速度慢

ArrayList是一个线程不安全的集合,运行速度快

ArrayList集合用法

  • 集合的构造方法 : new 无参数的构造方法
    • 创建长度为10个的集合, ArrayList底层是数组,数组的长度是10
  • 集合的构造方法 : new 有参数的构造方法,传递int类型参数
    • 参数是指定数组的长度的
  • 向集合存储元素,和取出元素
public static void main(String[] args) {
    //定义集合,存储自定义的对象Person
    ArrayList<Person> array = new ArrayList<Person>();
    array.add( new Person("张三",20) );
    array.add( new Person("李四",21) );
    array.add( new Person("王五",22) );

    //迭代器遍历
    Iterator<Person> it = array.iterator();
    while(it.hasNext()) {
        Person p = it.next();
        System.out.println(p);
    }
    System.out.println("===========");
    /*
		 * List接口实现类,ArrayList集合具有索引
		 * 利用索引来遍历  集合方法size()
		 * get(索引) 返回对应的元素
		 */
    for(int i = 0 ; i < array.size() ; i++) {
        Person p = array.get(i);
        System.out.println(p);
    }
}

ArrayList集合数组扩容 新容量 = 老容量 + 老容量/2

LinkedList集合

java.util.LinkedList 实现List接口 (有序,索引,重复)

底层数据结果是链表结构, 双向链表

查询速度慢,增删速度快

线程不安全的,运行速度快

特性的内容 : 专门有方法,操作链表的开头元素和结尾元素

LinkedList特有方法

  • 向链表的开头和结尾插入元素
    • addFirst(元素) 链表开头插入元素
    • addLast(元素)链表结尾插入元素
  • 获取链表的开头和结尾元素
    • 元素 getFirst() 获取链表的开头元素
    • 元素 getLast() 获取链表的结尾元素
  • 删除链表的开头和结尾元素
    • 元素 removeFirst() 删除链表的开头元素,返回被删除的元素
    • 元素 removeLast() 删除链表的结尾元素,返回被删除的元素
  • push和pop方法
    • push(元素)元素压入栈中
    • 元素 pop()栈中弹出元素
public static void main(String[] args) {
		myPushPop();
	}
	/*
	 * push()
	 * pop()
	 */
	public static void myPushPop() {
		LinkedList<String> link = new LinkedList<String>();
		link.add("a");
		link.add("b");
		link.add("c");
		link.add("d");
		System.out.println(link);
		//栈中推入元素
		link.push("e"); //开头添加
		System.out.println(link);
		
		//栈中弹出元素
		String pop = link.pop(); //移除开头
		System.out.println(pop);
		System.out.println(link);
	}
	
	/*
	 * removeFirst()
	 * removeLast()
	 */
	public static void myRemove() {
		LinkedList<String> link = new LinkedList<String>();
		link.add("a");
		link.add("b");
		link.add("c");
		link.add("d");
		System.out.println(link);
		//移除链表开头和结尾
		String first = link.removeFirst();
		String last = link.removeLast();
		System.out.println(first);
		System.out.println(last);
		System.out.println(link);
	}
	
	/*
	 * getFirst()
	 * getLast()
	 */
	public static void myGet() {
		LinkedList<String> link = new LinkedList<String>();
		link.add("a");
		link.add("b");
		link.add("c");
		link.add("d");
		System.out.println(link);	
		//获取开头和结尾元素
		String first = link.getFirst();
		String last = link.getLast();
		System.out.println(first);
		System.out.println(last);
		System.out.println(link);	
	}
	
	/*
	 * addFirst()
	 * addLast()
	 */
	public static void myAdd() {
		LinkedList<String> link = new LinkedList<String>();
		link.add("a");
		link.add("b");
		link.addLast("h");
		link.add("c");
		link.add("d");
		System.out.println(link);
		
		//开头插入元素
		link.addFirst("e");
		System.out.println(link);
		
		//尾部插入元素
		link.addLast("f");
		System.out.println(link);
	}

Map集合

Java.util.map接口,也是集合容器

●Collection集合存储元素每次只能存储单个的元素

●Map集合存储元素每次需要存储两个元素

  • 一个元素做为键,一个元素做为值

  • 一个集合中,键必须保证唯-性

  • 一个键只能映射一一个值

Map接口的方法

  • v put(k,v),将键值对存储到集合中
  • v get(k) 返回对应的值,集合中没有这个键,返回null
  • boolean containsValue(V) 判断集合中是否包含此值,包含返回true
  • V remove(K)移除集合中的键值对,返回被移除之前的值
  • Conllection<V> values() 集合中的所有的值取出,存储到Collection集合
public static void main(String[] args) {
		myput();
		myget();
		myContains();
		myremove();
		myvalues();
	}
	/*
	 * Map接口方法values()
	 */
	public static void myvalues() {
		//创建Map集合,键是字符串,值是整数
		Map<String , Integer> map = new HashMap<>();
		map.put("a", 1);
		map.put("b", 3);
		map.put("c", 4);
		
		Collection<Integer> coll = map.values();
		for(Integer integer : coll) {
			
			System.out.println(integer);
		}
	}
	/*
	 * Map接口方法remove
	 */
	public static void myremove() {
		//创建Map集合,键是字符串,值是整数
		Map<String , Integer> map = new HashMap<>();
		map.put("a", 1);
		map.put("b", 3);
		map.put("c", 4);
		//集合方法remove,移除键值对
		Integer value = map.remove("c");
		System.out.println(map);
		
	}
	/*
	 * Map接口方法 containsKey,contiansValue
	 */
	public static void myContains() {
		//创建Map集合,键是字符串,值是整数
		Map<String , Integer> map = new HashMap<>();
		map.put("a", 1);
		map.put("b", 3);
		map.put("c", 4);
		//判断是否包含键
		boolean b = map.containsKey("a");
		System.out.println(b);
		
		//判断是否包含此值
		boolean v = map.containsValue(1);
		System.out.println(v);
}
	/*
	 * Map接口方法get
	 */
	public static void myget() {
		//创建Map集合,键是字符串,值是整数
		Map<String , Integer> map = new HashMap<>();
		map.put("a", 1);
		map.put("b", 3);
		map.put("c", 4);
		//集合方法get(),传递键,获取值
		//如果对应的键没有值,就返回null
		Integer value = map.get("d");
		System.out.println(value);
	}

	/*
	 * Map接口方法put
	 */
	public static void myput() {
		//创建Map集合,键是字符串,值是整数
		Map<String , Integer> map = new HashMap<>();
		//集合方法put存储键值对
		map.put("a", 1);
		map.put("b", 3);
		map.put("c", 4);
		//键有重复时,前一个值会被覆盖
		map.put("d", 3);
		map.put("d", 5);
		System.out.println(map);
	}

Map集合遍历一

Map的遍历方式:键找值方式

Map接口定义方法:Set<k>keySet( ) Map集合的键,取出,存储在set集合

public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		map.put("abc", 123);
		map.put("bcd", 124);
		map.put("cde", 345);
		
		//map集合方法keyset()获取 存储键的set集合
		Set<String> set = map.keySet();
		//遍历Set集合
		Iterator<String> iterator = set.iterator();
		while(iterator.hasNext()) {
			//取出set集合元素,Map的键
			String key = iterator.next();
			//map集合键,找值
			Integer value = map.get(key);
			System.out.println(key+"=="+value);
		}
	}

Map集合遍历二

键值对的映射关系遍历,Map.Entry接口,实现类对象表示了键值对的对应关系,拿到Map.Entry接口实现类对象

  • Entry接口的方法
    • K getKey()取出集合中的键
    • V getValue()取出集合中的值
  • Map接口定义方法
    • Set<Entry<K,V>> entrySet()集合中的键值对映射关系对象,Entry接口对象存储在Set集合
public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		map.put("abc", 123);
		map.put("bcd", 124);
		map.put("cde", 345);
		
		//1.Map集合方法entrySet() 获取到Entry接口实现类对象,存储Set集合
		Set<Map.Entry<String,Integer>> set = map.entrySet();
		//2.遍历set集合
		Iterator<Map.Entry<String,Integer>> iterator = set.iterator();
		while(iterator.hasNext()) {
			//3.取出Set集合中的元素,是Entry接 口的实现类对象(键值对的对应关系)
			Map.Entry<String, Integer> entry  = iterator.next();
			//4.Entry接口对象,调用方法getKey(), getValue()
			String key = entry.getKey();
			Integer value =  entry.getValue();
			System.out.println(key+"=="+value);
		}

增强for循环间接遍历Map集合

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);
		Set<Map.Entry<String, Integer>> set = map.entrySet();
		for (Entry<String, Integer> entry : set) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key + "  = " + value);
		}
	}

HashMap

java.util.HashMap类实现Map接口

  • HashMap集合特点
    • 底层是哈希表结构,数组+链表(jdk1.8后变成数组+链表+红黑树)
    • 保证存储到键对象的唯一性,作为键的对象,必须重写hashcode和equals
    • 链表长度达8个,转成红黑树(尾插)
    • 集合运行存储null值,null键

LinkedHashMap

java. uti1. LinkedHashMap类继承HashMap,实现Map接口

java. uti1. LinkedHashset类继承HashSet实现Set接口

  • LinkedHashMap集合特点
    • 底层数据结构是哈希表,子类是双向链表

    • 集合是有序的集合,存储和取出的顺序一致

    • 线程不安全集合,运行速度快

public static void main(String[] args) {
LinkedHashMap<String,String> linked = new LinkedHashMap<String,String>();

	linked.put("b", "2");
	linked.put("a", "3");
	linked.put("h", "4");
	linked.put("g", "5");
	System.out.println(linked);
}
```

Hashtable

java. uti1. Hashtable类实现Map接口

  • Hashtable集合特点
    • 底层是哈希表结构
    • 不能存null值nul键(抛出空指针异常)
    • 线程安全的集合,运行速度慢
    • 从JDK1.2版本开始,被更加先进的HashMap取代
  • Vector集合, List接口实现类
    • 线程安全的,可变数组实现
    • 从JDK1.2开始,被更加先进的ArrayList取代

Properties

集合框架和数组,属于临时性数据,数据在内存中存储

程序退出了,关机了,数据就会消失

和IO流技术结合,实现数据的持久化

java.util.Properties类,继承Hashtable,实现接口Map

键值对存储的集合,所有的Map的使用方式,在Properties中全部使用

没有泛型的集合,类定义中,没有使用泛型技术

Properties集合中键值对的数据类型,被锁定为String类型

Properties设计失误的类

不能使用多态,设计存在失误

Properties特有的方法
  • setProperty(String key,String value)键值对存储到集合中,setProperty == put
  • getProperty(String key)返回指定键值对的值
  • stringPropertyNames()集合的全部键,存储到Set集合
public static void main(String[] args) {
		//创建集合对象
		Properties properties = new Properties();
		
		//存储键值对
		properties.setProperty("a", "1");
		properties.setProperty("b", "2");
		properties.setProperty("c", "3");
		
		System.out.println(properties);
		
		//取出键值对
		String value = properties.getProperty("a");
		System.out.println(value);
		
		//遍历集合
		Set<String > set = properties.stringPropertyNames();
		Iterator<String> iterator = set.iterator();
		while(iterator.hasNext()) {
			String key = iterator.next();
			String value1 = properties.getProperty(key);
			System.out.println(key+"=="+value1);
		}
	}

集合面试题

HashMap 和 Hashtable 有什么区别?
  • hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
  • hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
  • hashMap允许空键值,而hashTable不允许。
如何决定使用 HashMap 还是 TreeMap?

对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。

HashMap的底层原理

HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。

需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

HashSet的底层原理
  • HashSet底层由HashMap实现
  • HashSet的值存放于HashMap的key上
  • HashMap的value统一为PRESENT
ArrayList 和 LinkedList 的区别是什么?

最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。

如何实现数组和 List 之间的转换?

List转换成为数组:调用ArrayList的toArray方法。
数组转换成为List:调用Arrays的asList方法。

ArrayList 和 Vector 的区别是什么?

Vector是同步的,而ArrayList不是。然而,如果你寻求在迭代的时候对列表进行改变,你应该使用CopyOnWriteArrayList。
ArrayList比Vector快,它因为有同步,不会过载。
ArrayList更加通用,因为我们可以使用Collections工具类轻易地获取同步列表和只读列表。

Array 和 ArrayList 有何区别?

Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
Array是指定大小的,而ArrayList大小是固定的。
Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。

在 Queue 中 poll()和 remove()有什么区别?

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

哪些集合类是线程安全的?

vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
statck:堆栈类,先进后出。
hashtable:就比hashmap多了个线程安全。
enumeration:枚举,相当于迭代器。

迭代器 Iterator 是什么?

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

Iterator 怎么使用?有什么特点?

Java中的Iterator功能比较简单,并且只能单向移动:

  1. 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

  2. 使用next()获得序列中的下一个元素。

  3. 使用hasNext()检查序列中是否还有元素。

  4. 使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

Iterator 和 ListIterator 有什么区别?

Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java集合框架Java语言中用于存储和操作数据的一组接口和类的集合。它提供了各种数据结构,如List、Set、Map等,以及对这些数据结构的操作方法。Java集合框架具有以下特点: 1. 动态增长:集合框架中的数据结构可以根据需要自动扩展或收缩。 2. 类型安全:集合框架使用泛型来确保编译时类型检查,提高代码的安全性和可读性。 3. 高性能:集合框架提供了高效的数据结构和算法,以提供最佳的性能。 4. 多线程安全:集合框架提供了多个线程安全的集合类,可以在多线程环境中使用。 Java集合框架主要包括以下接口和类: . Collection接口:代表一组对象,提供了基本的集合操作方法,如添加、删除、查询等。 2. List接口:代表有序的集合,可以包含重复元素。 3. Set接口:代表无序的集合,不允许包含重复元素。 4. Map接口:代表键值对的集合,其中每个键都是唯一的。 5. ArrayList类:实现了List接口,使用数组实现的动态数组。 6. LinkedList类:实现了List接口,使用双向链表实现的链表。 7. HashSet类:实现了Set接口,使用哈希表实现的无序集合。 8. TreeSet类:实现了Set接口,使用红黑树实现的有序集合。 9. HashMap类:实现了Map接口,使用哈希表实现的键值对集合。 10. TreeMap类:实现了Map接口,使用红黑树实现的有序键值对集合

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值