栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java集合

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java集合

文章目录
  • 集合和数组的区别:
  • 请你列出你常用的集合框架中的类与接口(Java集合框架的基础接口有哪些?)
  • Collection方法
  • List,Set,Map三者的区别?
    • List:存取有序、可重复
    • Set:存取无序,不包含重复元素
    • Map:键值对
  • 迭代器 Iterator 是什么?
  • Iterator 和 ListIterator 有什么区别?
  • 遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么?
  • 说一下 ArrayList 的优缺点
  • ArrayList 和 LinkedList 的区别是什么?
  • ArrayList 和 Vector 的区别是什么?
  • 插入数据时,ArrayList、LinkedList、Vector谁速度较快?阐述 ArrayList、Vector、LinkedList 的存储性能和特性?
  • 为什么要重写equals和hashcode方法?
  • HashSet与TreeSet的区别
    • HashSet
    • TreeSet
    • 区别
  • HashSet与HashMap的区别
  • Collection 和 Collections 有什么区别?
  • HashMap 与 HashTable 有什么区别?


集合和数组的区别:
  • 数组是固定长度的;集合可变长度的。
  • 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型
  • 数组存储的元素必须是一个数据类型;集合存储的对象可以是不同数据类型。

请你列出你常用的集合框架中的类与接口(Java集合框架的基础接口有哪些?)

Map接口和Collection接口是所有集合框架的父接口

  • Collection接口的子接口包括:Set接口和List接口
    • List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等
    • Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等
  • Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等
Collection方法
Collection集合常用方法:
    boolean add(E e):添加元素
    boolean remove(Object o):从集合中移除指定的元素
    void clear():清空集合中的元素
    boolean contains(Object o):判断集合中是否存在指定的元素
    boolean isEmpty():判断集合是否为空
    int size():集合的长度,也就是集合中元素的个数
package 集合;

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


public class CollectionDemo01 {
    public static void main(String[] args) {
        //创建Collection集合的对象
        Collection c = new ArrayList();


    

        //boolean add(E e):添加元素
        c.add("hello");
        c.add("world");
        c.add("java");
        System.out.println(c);//[hello, world, java]
        System.out.println("------------------------------");
        //boolean remove(Object o):从集合中移除指定的元素
        System.out.println(c.remove("world"));//true
        System.out.println(c.remove("javaee"));//false
        System.out.println(c);//[hello, java]
        System.out.println("------------------------------");
        //void clear():清空集合中的元素
        c.clear();
        System.out.println(c);//[]
        System.out.println("------------------------------");
        //boolean contains(Object o):判断集合中是否存在指定的元素
        c.add("hh");
        c.add("oo");
        c.add("java");
        System.out.println(c.contains("world"));//false
        System.out.println(c.contains("java"));//true
        System.out.println("------------------------------");
        //boolean isEmpty():判断集合是否为空
        System.out.println(c.isEmpty());//false
        System.out.println("------------------------------");
        //int size():集合的长度,也就是集合中元素的个数
        System.out.println(c.size());//3

        //输出集合对象
        System.out.println(c);//[hh, oo, java]
        System.out.println("------------------------------");
        
        //Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
        Iterator it = c.iterator();
        //E next():返回迭代中的下一个元素
        System.out.println(it.next());//hh
        System.out.println(it.next());//oo
        System.out.println(it.next());//java
        //System.out.println(it.next());//NoSuchElementException:表示被请求的元素不存在
        System.out.println("------------------------------");
        //boolean hasNext():如果迭代具有更多元素,则返回 true
        //用while循环改进判断
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }


    }
}

List,Set,Map三者的区别?
  • Collection集合主要有List和Set两大接口

  • List:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。

  • Set:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet。

  • Map是一个键值对集合,存储键、值和之间的映射。 Key无序,唯一;value 不要求有序,允许重复。Map没有继承于Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
    Map的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap

List:存取有序、可重复

List集合特有方法:

    void add(int index,E element):在此集合中的指定位置插入指定的元素
    E remove(int index):删除指定索引处的元素,返回被删除的元素
    E set(int index,E element):修改指定索引处的元素,返回被修改的元素
    E get(int index):返回指定索引处的元素
package 集合.List;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


public class ListDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        List list = new ArrayList();

        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("world");

        //输出集合对象
        System.out.println(list);//[hello, world, java, world]
        System.out.println("------------------------------");
        //迭代器的方式遍历
        Iterator it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }

        System.out.println("------------------------------");
    
        //void add(int index,E element):在此集合中的指定位置插入指定的元素
        list.add(1,"add");
        System.out.println(list);//[hello, add, world, java, world]
        System.out.println("------------------------------");
        //IndexOutOfBoundsException
        //list.add(11,"addout");
        //System.out.println(list);
        //System.out.println("------------------------------");

        //E remove(int index):删除指定索引处的元素,返回被删除的元素
        System.out.println(list.remove(1));
        System.out.println(list);//[hello, world, java, world]
        System.out.println("------------------------------");
        //IndexOutOfBoundsException
        //System.out.println(list.remove(11));
        //System.out.println(list);//[hello, add, world, java, world]
        //System.out.println("------------------------------");

        //E set(int index,E element):修改指定索引处的元素,返回被修改的元素
        System.out.println(list.set(1,"repair"));//word
        System.out.println("------------------------------");
        //IndexOutOfBoundsException
        //System.out.println(list.set(11,"javaee"));
        //System.out.println("------------------------------");

        //E get(int index):返回指定索引处的元素
        System.out.println(list.get(1));//repair
        System.out.println("------------------------------");
        //IndexOutOfBoundsException
        //System.out.println(list.get(11));
        //System.out.println("------------------------------");

        //输出集合对象
        System.out.println(list);//[hello, repair, java, world]
        System.out.println("------------------------------");
        //遍历集合
        System.out.println(list.get(0));//hello
        System.out.println(list.get(1));//repair
        System.out.println(list.get(2));//java
        System.out.println("------------------------------");
        //用for循环改进遍历
        for (int i=0; i
            String s = list.get(i);
            System.out.println(s);
        }
        System.out.println("------------------------------");

        //遍历集合,得到每一个元素,看有没有"world"这个元素,
        for(int i=0; i
            String s = list.get(i);
            if(s.equals("world")) {
                list.add("add");
            }
        }
        System.out.println(list);//[hello, repair, java, world, add]
    }
}

Set:存取无序,不包含重复元素
package 集合.Set;

import java.util.HashSet;
import java.util.Set;


public class SetDemo {
    public static void main(String[] args) {
        //创建集合对象
        Set set = new HashSet();

        //添加元素
        set.add("hello");
        set.add("world");
        set.add("java");
        //不包含重复元素的集合
        set.add("world");

        //遍历
        for(String s : set) {
            System.out.println(s);
        }

    }
}

Map:键值对
package 集合.Map;

import java.util.HashMap;
import java.util.Map;


public class MapDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        Map map = new HashMap();

        //V put(K key, V value) 将指定的值与该映射中的指定键相关联
        map.put("001","hh1");
        map.put("002","hh2");
        map.put("003","hh3");
        map.put("003","hh4");

        //输出集合对象
        System.out.println(map);//{001=hh1, 002=hh2, 003=hh4}
    }
}

Map集合的基本功能:
    V put(K key,V value):添加元素
    V remove(Object key):根据键删除键值对元素
    void clear():移除所有的键值对元素
    boolean containsKey(Object key):判断集合是否包含指定的键
    boolean containsValue(Object value):判断集合是否包含指定的值(自学)
    boolean isEmpty():判断集合是否为空
    int size():集合的长度,也就是集合中键值对的个数
Map集合的获取功能:
    V get(Object key):根据键获取值
    Set keySet():获取所有键的集合
    Collection values():获取所有值的集合
  Map集合的遍历1:
      1:获取所有键的集合。用keySet()方法实现
      2:遍历键的集合,获取到每一个键。用增强for实现
      3:根据键去找值。用get(Object key)方法实现
//获取所有键的集合。用keySet()方法实现
Set keySet = map.keySet();
//遍历键的集合,获取到每一个键。用增强for实现
for (String key : keySet) {
    //根据键去找值。用get(Object key)方法实现
    String value = map.get(key);
    System.out.println(key + "," + value);
}
Map集合的遍历2:
    1:获取所有键值对对象的集合
        Set> entrySet():获取所有键值对对象的集合
    2:遍历键值对对象的集合,得到每一个键值对对象
        用增强for实现,得到每一个Map.Entry
    3:根据键值对对象获取键和值
        用getKey()得到键
        用getValue()得到值
    //获取所有键值对对象的集合
    Set> entrySet = map.entrySet();
    //遍历键值对对象的集合,得到每一个键值对对象
    for (Map.Entry me : entrySet) {
        //根据键值对对象获取键和值
        String key = me.getKey();
        String value = me.getValue();
        System.out.println(key + "," + value);
    }

代码练习

package 集合.Map;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


public class MapDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Map map = new HashMap();

        //V put(K key,V value):添加元素
        map.put("001","hh1");
        map.put("002","hh2");
        map.put("003","hh3");

        //V remove(Object key):根据键删除键值对元素
        System.out.println(map.remove("001"));//hh1
        System.out.println(map.remove("001"));//null
        System.out.println("-------------------------------");
        //void clear():移除所有的键值对元素
        map.clear();
        System.out.println(map);//{}
        System.out.println("-------------------------------");

        //boolean containsKey(Object key):判断集合是否包含指定的键
        map.put("001","hh1");
        map.put("002","hh2");
        map.put("003","hh3");
        System.out.println(map.containsKey("002"));//true
        System.out.println(map.containsKey("001"));//true
        System.out.println("-------------------------------");

        //boolean isEmpty():判断集合是否为空
        System.out.println(map.isEmpty());//false
        System.out.println("-------------------------------");

        //int size():集合的长度,也就是集合中键值对的个数
        System.out.println(map.size());//3
        System.out.println("-------------------------------");

        
        //Collection values():获取所有值的集合
        Collection values = map.values();
        for(String value : values) {
            System.out.println(value);
        }
        
        System.out.println("-------------------------------");

        
        //获取所有键的集合。用keySet()方法实现
        Set keySet = map.keySet();
        //遍历键的集合,获取到每一个键。用增强for实现
        for (String key : keySet) {
            //根据键去找值。用get(Object key)方法实现
            String value = map.get(key);
            System.out.println(key + "," + value);
        }
        
        System.out.println("-------------------------------");
        
        //获取所有键值对对象的集合
        Set> entrySet = map.entrySet();
        //遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry me : entrySet) {
            //根据键值对对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "," + value);
        }

        

    }
}


迭代器 Iterator 是什么?

Iterator 接口提供遍历任何 Collection 的接口
Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到

Iterator中的常用方法
    E next():返回迭代中的下一个元素
    boolean hasNext():如果迭代具有更多元素,则返回 true
List list = new ArrayList<>();
Iterator it = list. iterator();
while(it. hasNext()){
  String s = it. next();
  System. out. println(s);
}

Iterator 和 ListIterator 有什么区别?
  • Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。
  • Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。
  • ListIterator 实现 Iterator 接口,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。

ListIterator:列表迭代器 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
用于允许程序员沿任一方向遍历列表的列表的迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

ListIterator中的常用方法
	E next():返回迭代中的下一个元素
	boolean hasNext():如果迭代具有更多元素,则返回 true
	E previous():返回列表中的上一个元素
	boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 true
	void add(E e):将指定的元素插入列表
package 集合.List;

import java.util.LinkedList;


public class LinkedListDemo {
    public static void main(String[] args) {
        //创建集合对象
        LinkedList linkedList = new LinkedList();

        linkedList.add("hello");
        linkedList.add("world");
        linkedList.add("java");

//        public void addFirst(E e):在该列表开头插入指定的元素
//        public void addLast(E e):将指定的元素追加到此列表的末尾
        linkedList.addFirst("addfirst");
        System.out.println(linkedList);//[addfirst, hello, world, java]
        System.out.println("-------------------------");
        linkedList.addLast("addlast");
        System.out.println(linkedList);//[addfirst, hello, world, java, addlast]
        System.out.println("-------------------------");

//        public E getFirst():返回此列表中的第一个元素
//        public E getLast():返回此列表中的最后一个元素
        System.out.println(linkedList.getFirst());//addfirst
        System.out.println(linkedList.getLast());//addlast
        System.out.println("-------------------------");

//        public E removeFirst():从此列表中删除并返回第一个元素
//        public E removeLast():从此列表中删除并返回最后一个元素
        System.out.println(linkedList.removeFirst());//addfirst
        System.out.println(linkedList.removeLast());//addlast
        System.out.println("-------------------------");
        System.out.println(linkedList);//[hello, world, java]
    }
}

遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么?
  • for 循环遍历,基于计数器。在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后停止。
  • 迭代器遍历,Iterator。Iterator 是面向对象的一个设计模式,目的是屏蔽不同数据集合的特点,统一遍历集合的接口。Java 在 Collections 中支持了 Iterator 模式。
  • foreach 循环遍历。foreach 内部也是采用了 Iterator 的方式实现,使用时不需要显式声明 Iterator 或计数器。优点是代码简洁,不易出错;缺点是只能做简单的遍历,不能在遍历过程中操作数据集合,例如删除、替换。
		//迭代器:集合特有的遍历方式
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s.getName()+","+s.getAge());
        }
        System.out.println("--------");
 
        //普通for:带有索引的遍历方式
        for(int i=0; i
            Student s = list.get(i);
            System.out.println(s.getName()+","+s.getAge());
        }
        System.out.println("--------");
 
        //增强for:最方便的遍历方式
        for(Student s : list) {
            System.out.println(s.getName()+","+s.getAge());
        }

说一下 ArrayList 的优缺点
  • ArrayList的优点:
    ArrayList 底层以数组实现,是一种随机访问模式。ArrayList 实现了 RandomAccess 接口,因此查找的时候非常快。
    ArrayList 在顺序添加一个元素的时候非常方便。
  • ArrayList 的缺点:
    删除元素的时候,需要做一次元素复制操作。如果要复制的元素很多,那么就会比较耗费性能。
    插入元素的时候,也需要做一次元素复制操作,缺点同上。
    ArrayList 比较适合顺序添加、随机访问的场景
ArrayList 和 LinkedList 的区别是什么?
  • 数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
  • 随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
  • 增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。
  • 内存空间占用:LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
  • 线程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;
    在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。
ArrayList 和 Vector 的区别是什么?
  • 这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合
    • 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。
    • 性能:ArrayList 在性能方面要优于 Vector。
    • 扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。
  • Vector类的所有方法都是同步的。可以由两个线程安全地访问一个Vector对象、但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间。
  • Arraylist不是同步的,所以在不需要保证线程安全时时建议使用Arraylist。
插入数据时,ArrayList、LinkedList、Vector谁速度较快?阐述 ArrayList、Vector、LinkedList 的存储性能和特性?
  • ArrayList和Vector 底层的实现都是使用数组方式存储数据。数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。
  • Vector 中的方法由于加了 synchronized 修饰,因此 Vector 是线程安全容器,但性能上较ArrayList差。
  • LinkedList 使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但插入数据时只需要记录当前项的前后项即可,所以 LinkedList 插入速度较快。
为什么要重写equals和hashcode方法?

先通过hashcode方法返回的值,直接定位元素应该存储的物理位置,位置上没有元素则存放,若有元素,再比较对象的equals方法,从而大大减少equals方法调用,提高比较效率。

  • hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。
    • 如何获取哈希值
      Object类中的public int hashCode():返回对象的哈希码值,返回的就是根据对象的内存地址换算出的一个值

    • 对象的哈希值特点
      同一个对象多次调用hashCode()方法返回的哈希值是相同的
      默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

    • 为什么要有 hashCode

我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode:
  当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来   判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。
  但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。
  如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

hashCode()与equals()的相关规定

  • 如果两个对象相等,则hashcode一定也是相同的
  • 两个对象相等,对两个对象分别调用equals方法都返回true
  • 两个对象有相同的hashcode值,它们也不一定是相等的
    因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
    hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
package 集合.Set;

import 集合.StudentTest;
import 面向对象.Student;


public class HashDemo {
    public static void main(String[] args) {
        //创建学生对象
        StudentTest s1 = new StudentTest("hashcode",30);

        //同一个对象多次调用hashCode()方法返回的哈希值是相同的
        System.out.println(s1.hashCode()); //1163157884
        System.out.println(s1.hashCode()); //1163157884
        System.out.println("--------");

        StudentTest s2 = new StudentTest("hashcode",30);

        //默认情况下,不同对象的哈希值是不相同的
        //通过方法重写,可以实现不同对象的哈希值是相同的
        System.out.println(s2.hashCode()); //1956725890
        System.out.println("--------");

        System.out.println("hello".hashCode()); //99162322
        System.out.println("world".hashCode()); //113318802
        System.out.println("java".hashCode()); //3254818

        System.out.println("world".hashCode()); //113318802
        System.out.println("--------");

        System.out.println("重地".hashCode()); //1179395
        System.out.println("通话".hashCode()); //1179395


    }
}


HashSet与TreeSet的区别 HashSet

HashSet集合特点

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以是不包含重复元素的集合

HashSet 集合保证元素唯一性的原理

  • 根据对象的哈希值计算存储位置
    • 如果当前位置没有元素则直接存入
    • 如果当前位置有元素存在,则进入第二步
  • 当前元素的元素和已经存在的元素比较哈希值
    • 如果哈希值不同,则将当前元素进行存储
    • 如果哈希值相同,则进入第三步
  • 通过 equals() 方法比较两个元素的内容
    • 如果内容不相同,则将当前元素进行存储
    • 如果内容相同,则不存储当前元素
package 集合.Set;

import java.util.HashSet;


public class HashSetDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        HashSet hs = new HashSet();

        //添加元素
        hs.add("hello");
        hs.add("world");
        hs.add("hashset");

        hs.add("world");

        //遍历
        for(String s : hs) {
            System.out.println(s);
        }
        
    }
}
TreeSet
  • 元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法
    • TreeSet():根据其元素的自然排序进行排序
    • TreeSet(Comparator comparator) :根据指定的比较器进行排序
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以不包含重复元素的集合
package 集合.Set;


import 集合.StudentTest;
import 面向对象.Student;

import java.util.Comparator;
import java.util.TreeSet;


public class TreeSetDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet ts = new TreeSet();

        //添加元素
        ts.add(10);
        ts.add(40);
        ts.add(30);
        ts.add(50);
        ts.add(20);

        ts.add(30);

        //遍历集合
        for(Integer i : ts) {
            System.out.println(i);
        }

        //创建集合对象
        TreeSet ts2 = new TreeSet();

        //创建学生对象
        StudentTest s1 = new StudentTest("hh1", 1);
        StudentTest s2 = new StudentTest("hh2", 2);
        StudentTest s3 = new StudentTest("hh3", 5);
        StudentTest s4 = new StudentTest("hh4", 2);

        StudentTest s5 = new StudentTest("hh5",2);
        StudentTest s6 = new StudentTest("hh6",2);

        //把学生添加到集合
        ts2.add(s1);
        ts2.add(s2);
        ts2.add(s3);
        ts2.add(s4);
        ts2.add(s5);
        ts2.add(s6);

        //遍历集合
        for (StudentTest s : ts2) {
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}
区别

区别一:

  • TreeSet 是二叉树实现的,Treeset中的数据是要求泛型对象实现自然顺序或自定义排序,不允许放入null值。

  • HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。

区别二:

  • HashSet要求放入的对象重写equals()、hashCode()方法,对象放入集合中首先是以hashcode码作为标识。

  • TreeSet判断两个对象不相等的方式是通过排序实现

    • 自然排序
      comparable接口实际上是出自java.lang包,它有一个 compareTo(Object obj)方法用来排序。
      自然排序要实现Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。obj1.compareTo(obj2),若返回0,则说明被比较的两个对象相等,若返回一个正数,则表明obj1大于obj2,若返回负数,则表明obj1小于obj2。
    @Override
    public int compareTo(StudentTest s) {
//        return 0;
//        return 1;
//        return -1;
        //按照年龄从小到大排序
        int num = this.age - s.age;
//        int num = s.age - this.age;
        //年龄相同时,按照姓名的字母顺序排序
        int num2 = num==0?this.name.compareTo(s.name):num;
        return num2;
    }
  • 自定义排序
    comparator接口实际上是出自 java.util 包,它有一个compare(Object obj1, Object obj2)方法用来排序。
    自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现 int compare(T o1,T o2)方法。
		//创建集合对象
      TreeSet ts3 = new TreeSet(new Comparator() {
          @Override
          public int compare(Student s1, Student s2) {
              //this.age - s.age
              //s1,s2
              int num = s1.getAge() - s2.getAge();
              int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
              return num2;
          }
      });
HashSet与HashMap的区别
HashMapHashSet
实现了Map接口实现Set接口
存储键值对仅存储对象
调用put()向map中添加元素调用add()方法向Set中添加元素
HashMap使用键(Key)计算HashcodeHashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
HashMap相对于HashSet较快,因为它是使用唯一的键获取对象HashSet较HashMap来说比较慢
Collection 和 Collections 有什么区别?
  • java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
  • Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
Collections类:是针对集合操作的工具类
Collections类的常用方法:
public static > void sort(List list):将指定的列表按升序排序
public static void reverse(List list):反转指定列表中元素的顺序
public static void shuffle(List list):使用默认的随机源随机排列指定的列表
HashMap 与 HashTable 有什么区别?
  • 线程安全: HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过 synchronized 修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap );
  • 效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它;(如果你要保证线程安全的话就使用 ConcurrentHashMap );
  • 对Null key 和Null value的支持: HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。但是在 HashTable 中 put 进的键值只要有一个 null,直接抛NullPointerException。
  • 初始容量大小和每次扩充容量大小的不同:
    创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。
    创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小。也就是说 HashMap 总是使用2的幂作为哈希表的大小。
  • 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。

在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/860413.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号