List集合与Set集合的区别(面试题)

一般来说,如果被别人问到一个问题:谁和谁的区别,在回答问题的时候,第一步应该回答的是他们之间有什么相似之处,充分变现出对技术的理解

相同点:ListSet都是Collection集合的子级接口!所以都具有Collection这个借口所定义的所有的方法,比如添加和移除元素。

不同点:List序列的,主要表现为其中的各元素在内存中是存在顺序规则的;另外,List中的元素是可以重复的,即可以向同一个List集合中反复添加相同的数据;

Set散列的,主要表现为其中的各元素在内存中的位置是散列的,如果使用不同的实现类来存储数据,最终在显示Set集合中的所有元素时,显示结果可能是无序的(HashSet),或根据排序规则进行排列的(TreeSet),或根据添加顺序进行排列的(LinkedHashSet);(注意并不是说整个集合是,而是最后的显示结果,看到的结果是这样的)。所以不能直接说Set是无序的

另外,Set中的元素是不可重复的,即不可以向同一个Set集合中反复添加相同的数据,关于“是否相同”,取决于equals()的对比结果与hashCode()值的对比,如果2个对象的equals()对比为true并且hashCode()值相等,则视为“相同”!

所以,是否相同,取决于hashCode和equals方法,是先比较的hashCode再比较equals,如果hashCode相同,再比较equals,如果hashCode不同,就不比较了。

一、注意:不要用有序和无序来描述List集合和Set集合

比如Set集合,要看用的是哪个实现类:

(1)使用HashSet作为实现类,结果是无序的;

(2)使用TreeSet作为实现类,结果为12345有序的;

(3)使用LinkedHashSet实现类,结果与添加顺序一致;

所以,直接说Set是无序的,这种说法是不精准的

详细如下:

1.使用HashSet作为实现类,输出为:[str-4, str-5, str-2, str-3, str-1],显示结果是无序的

package cn.tedu.spring;

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

public class CollectionDemo {
	public static void main(String[] args) {
		Set<String> strings = new HashSet<String>();
		strings.add("str-1");
		strings.add("str-5");
		strings.add("str-3");
		strings.add("str-2");
		strings.add("str-4");
		System.out.println(strings);
		//输出为:[str-4, str-5, str-2, str-3, str-1]
    }
}

2.使用TreeSet作为实现类,输出为[str-1, str-2, str-3, str-4, str-5],显示结果是有序的

package cn.tedu.spring;

import java.util.Set;
import java.util.TreeSet;

public class CollectionDemo {
	public static void main(String[] args) {
		Set<String> strings = new TreeSet<String>();
		strings.add("str-1");
		strings.add("str-5");
		strings.add("str-3");
		strings.add("str-2");
		strings.add("str-4");
		System.out.println(strings);
		//输出为:[str-1, str-2, str-3, str-4, str-5]
    }
}

3.使用 LinkedHashSet作为实现类,输出为:[str-1, str-5, str-3, str-2, str-4],和添加的顺序一致,显示结果是有序的

package cn.tedu.spring;

import java.util.LinkedHashSet;
import java.util.Set;

public class CollectionDemo {
	public static void main(String[] args) {
		Set<String> strings = new LinkedHashSet<String>();
		strings.add("str-1");
		strings.add("str-5");
		strings.add("str-3");
		strings.add("str-2");
		strings.add("str-4");
		System.out.println(strings);
		//输出为:[str-1, str-5, str-3, str-2, str-4]
    }
}        

所以,直接说Set是无序的,这种说法是不精准的

而对于Set中的元素是不可重复的:

演示代码:

package cn.tedu.spring;

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

public class CollectionDemo {

	public static void main(String[] args) {
		Set<String> strings = new LinkedHashSet<String>();
		strings.add("str-1");
		strings.add("str-5");
		strings.add("str-3");
		strings.add("str-2");
		strings.add("str-2");
		strings.add("str-2");
		strings.add("str-2");
		strings.add("str-2");
		strings.add("str-4");
		System.out.println(strings);
		
        //重点关注Set集合能不能重复,是哪个实现类不重要
		Set<Student> students = new HashSet<Student>();
		students.add(new Student("Mike", 18));
		students.add(new Student("Frank", 20));
		students.add(new Student("Frank", 20));
        //这行代码是复制上一行的
        //这个相同的student,是可以加入进去的,但绝对不是因为是new出来的这个原因
        
		students.add(new Student("Frank", 25));
		students.add(new Student("Joe", 25));
        //为了不一横排输出,写一个遍历好看些
		for (Student student : students) {
			System.out.println(student);
		}
	}

}

class Student {
	public String name;
	public int age;
	
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
    
    //下面的两个重写方法,都是用Source来生成的,一键生成
    //而开发工具不同,可能生成的代码是不同的
    //生成的这两个方法,目的是为了加入的属性值的内容相同,即使是new出来的对象,也看做同一个数据,也不能加入集合
    
    //各个属性,比如name和age的值相同,它的hashcode就一定相同,equals的对比结果也一定是true
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
    //下面这个是自动生成的
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}

如何输出Set集合中的单个元素?

一般Set集合,就是遍历输出,挨个输出里面的所有元素,

只有一种情况是输出Set中的单个元素,就是确定这Set的实现类是LinkedHashSet,因为Linked的元素存储结构是一个链一个的,所以在LinkedHashSet里面的数据其实是有下标的,或者说是有索引位置的,所以只有这种Set我们才会在当中获取第3个元素或第5个元素。如果是一般的HashSet或TreeSet我们根本就不考虑要获取其中的某一个。

上一篇:Mabatis的配置


下一篇:二维码扫一扫xss