List继承自Collection接口,是有序可重复的集合。java
它的实现类有:ArrayList、LinkedList、Vector、Stack算法
本质上是一个能存储任意类型的对象的动态数组,元素的删除和添加涉及到数组的扩容以及拷贝元素,因此效率很慢。因为数组是能够经过下标来查找的,所以查找速度快。数组
基于双向链表实现,增删快,查找慢。根据链表的性质,增长元素时只需让前一个元素记住本身就行,删除的时候让前一个元素记住后一个元素,后一个元素记住前一个元素,这种增删的效率比较高,但查找元素须要遍历链表,效率低。安全
public static void main(String[] args){ List<Dog> list = new LinkedList<>(); System.out.println(list.size()); Dog dog1 = new Dog("小苏","藏獒"); Dog dog2 = new Dog("小王","二哈"); Dog dog3 = new Dog("小李","金毛"); ((LinkedList<Dog>) list).addFirst(dog1); list.add(dog2); ((LinkedList<Dog>) list).addLast(dog3); System.out.println(list); System.out.println(((LinkedList<Dog>) list).getFirst()); System.out.println(list.get(1)); System.out.println(((LinkedList<Dog>) list).getLast()); }
基于数组实现,线程同步的遗留集合类,和ArrayList原理相同,可是线程安全,效率低。ide
后进先出this
Set继承自Collection接口,是无序不可重复的集合线程
它的实现类有HashSet、LinkedHashSet、TreeSetcode
基于哈希表实现,元素存储的地址是该元素的哈希值。对象
HashSet存储元素的步骤:blog
public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("邵阳---长沙"); set.add("武汉---南京"); set.add("合肥---北京"); set.add("武汉---南京"); System.out.println("-------第一种输出方式:toString方法--------"); System.out.println(set); System.out.println("-------第二种输出方式:加强for循环--------"); for (String str: set) { System.out.println(str); } System.out.println("-------第三种输出方式:迭代器方法--------"); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } // set集合是无序的,所以没有下标,没法用for循环来遍历 }
@Test public void setObject(){ Set<Student> set = new HashSet<>(); set.add(new Student("小贝 ",9)); set.add(new Student("小胡 ",19)); set.add(new Student("小贝 ",9)); set.add(new Student("小福 ",23)); Iterator<Student> iterator = set.iterator(); while (iterator.hasNext()){ /* * 因为hash表示无序的,所以输出结果可能和存储结果不一致 */ System.out.println(iterator.next().toString()); } /* * 若Student类重写了equals方法,则第二个小贝不会被存入set, * 这种状况下只会比较两个小贝的名字和年龄的值,由于两个小贝的名字和年龄同样,所以他们被认为是两个相同的对象 * 若Student类没有重写equals方法,则第二个小贝会被存入set, * 这种状况下只会比较两个小贝的地址,由于是两个不一样的对象因此地址不一样,所以他们被认为是两个不一样的对象 */ }
/* * 被重写的equals方法 */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); /* * 注意基本类型的变量直接用==比较,而对象类型的,分状况讨论: * 若只比较值,则用equals方法,由于String类重写了equals方法 */ }
基于哈希表和双向链表实现,元素有序且不可重复,存储步骤和HashSet一致,元素的顺序是其存储顺序
@Test public void printLinkedHashList() { Set<String> set = new LinkedHashSet<>(); set.add("绝地求生"); set.add("球球大做战"); set.add("守望先锋"); set.add("超级玛丽"); set.add("超级玛丽"); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } /* 输出结果和存储结果一致: * 绝地求生 * 球球大做战 * 守望先锋 * 超级玛丽 */ }
TreeSet是基于红黑树的有序且不可重复的集合,元素的顺序和元素自己有关,和存储顺序无关
/* * 这个方法在执行的时候会报错,由于在TreeSet在存储时不知道根据学生的姓名仍是年龄来排序,准确地说,Student * 类没有实现Comparable接口,所以没法对Student排序。将一组乱序的数字或字符串存入TreeSet,从新输出会获得* 一组有序的数据,由于String类默认实现了Comparable接口。 * 报错信息以下:java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable */ @Test public void testSort() { Set<Student> set = new TreeSet<>(); set.add(new Student("小贝 ",9)); set.add(new Student("小胡 ",19)); set.add(new Student("小贝 ",10)); set.add(new Student("小福 ",23)); Iterator<Student> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
/* * 对Student类进行修改,让他继承Comparable接口,并重写Comparable里的comparaTo方法,按照学生的年龄进行* 排序 */ public class Student implements Comparable<Student>{ private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public void comparaTo() { } @Override public int comparaTo(Student o) { /* * 结果为负,排在o对象以前 * 结果为正,排在o对象以后 * 结果为0, 说明两个对象相等 */ return this.age - o.age; } }