集合,集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?
数组的长度是固定的。集合的长度是可变的。
集合中存储的元素必须是引用类型数据
集合继承关系
Collection接口为最顶层集合接口~
Collecton接口常用的子接口有:
List接口、Set接口
List接口常用的子类有:ArrayList类、LinkedList类
Set接口常用的子类有:HashSet类、LinkedHashSet类
Collection 接口 | ---------------------------------------------------------------- | | List接口 Set接口 | | ---------------- ------------- | | | | ArrayList类 LinkedList类 HashSet类 LinkedHashSet类
所有继承List接口的集合都是有序且可重复的集合并且先进后出。ArrayList是数组,LinkedList底层是链表
ArrayList:查询快,增删慢。
因为ArrayList中的数据在内存中是连续的,成块的,查找的时候直接顺序遍历内存就可以了。
插入删除的时候,就要把修改的那个节点之后的所有数据都向后移动,或者向前移动。所以就慢了。
LinkedList:查询慢,增删快
因为LinkedList是使用类似于链表来存储的,c与arraylist相反,增删只要添加一个连接就可以了,
不要移动后面的所有元素,查询的时候每一个节点都有一个指针指向下一个节点,这样查找起来就比较慢了。
数组,采用该结构的集合,对元素的存取有如下的特点:
n 查找元素快:通过索引,可以快速访问指定位置的元素
n 增删元素慢:
u 指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。如下图
u 指定索引位置删除元素:需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。如下图
l 链表,采用该结构的集合,对元素的存取有如下的特点:
n 多个节点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
n 查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素
n 增删元素快:
u 增加元素:操作如左图,只需要修改连接下个元素的地址即可。
u 删除元素:操作如右图,只需要修改连接下个元素的地址即可。
set:所有继承Set接口的集合都是无序且不可重复的集合并没有索引,其他和list基本相同。
HashSet:无序,不可重复,底层是哈希表,通过重写对象中的hashCode和equals方法,
建立自己的比较方式,可保证HashSet集合中的对象唯一.
HashSet:集合自身的特点:底层数据结构,哈希表
查询快,增删也快
线程不安全,运行速度快
有一点,哈希表存的数据越多,查询越慢
证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。
如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。
比如String str = new String(123);
String str2 = new String(123);
先调一个查询哈希值得方法,然后在对比equest方法。
HashSet :存储自定义类型元素,保证对象的唯一性。
创建自定义对象Student public class Student { private String name; private int age; public Student(String name, int age) { super(); 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 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 instanceof Student)){ System.out.println("类型错误"); return false; } Student other = (Student) obj; return this.age == other.age && this.name.equals(other.name); } } 创建HashSet集合,存储Student对象。 public class HashSetDemo { public static void main(String[] args) { //创建HashSet对象 HashSet hs = new HashSet(); //给集合中添加自定义对象 hs.add(new Student("zhangsan",21)); hs.add(new Student("lisi",22)); hs.add(new Student("wangwu",23)); hs.add(new Student("zhangsan",21)); //取出集合中的每个元素 Iterator it = hs.iterator(); while(it.hasNext()){ Student s = (Student)it.next(); System.out.println(s); } } } 输出结果如下,说明集合中不能存储重复元素: Student [name=lisi, age=22] Student [name=zhangsan, age=21] Student [name=wangwu, age=23]
LinkedHashSet:它是HashSet的一个子类,它是链表和哈希表组合的一个数据结构。
演示代码如下: public class LinkedHashSetDemo { public static void main(String[] args) { Set<String> set = new LinkedHashSet<String>(); set.add("bbb"); set.add("aaa"); set.add("abc"); set.add("bbc"); Iterator it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } 输出结果如下,LinkedHashSet集合保证元素的存入和取出的顺序: bbb aaa abc bbc
list集合给自定义对象排序:
Student学生类:
package com; public class Student { private int studentId; private String studentName; private int age; public Student(int studentId , String studentName, int age){ this.studentId=studentId; this.studentName=studentName; this.age=age; } public int getStudentId() { return studentId; } public void setStudentId(int studentId) { this.studentId = studentId; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
排序类:
package com; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class main { public static void main(String[] args) { Comparator<Student> comparator = new Comparator<Student>() { public int compare(Student s1, Student s2) { // 先排年龄 if (s1.getAge() != s2.getAge()) { return s1.getAge() - s2.getAge(); } else if (!s1.getStudentName().equals(s2.getStudentName())) { // 年龄相同则按姓名排序 return s1.getStudentName().compareTo(s2.getStudentName()); } else { // 姓名也相同则按学号排序 return s1.getStudentId() - s2.getStudentId(); } } }; Student stu1 = new Student (1,"zhangsan",28); Student stu2 = new Student (2,"zhagnsan",19); Student stu3 = new Student (3,"wangwu",19); Student stu4 = new Student (4,"wangwu",19); Student stu5 = new Student (5,"zhaoliu",18); ArrayList<Student> list = new ArrayList<Student>(); list.add(stu1); list.add(stu2); list.add(stu3); list.add(stu4); list.add(stu5); //这里就会自动根据规则进行排序 Collections.sort(list,comparator); for(int i=0;i<list.size();i++){ Student stu=list.get(i); System.out.println("年龄:"+stu.getAge()+" 姓名:"+stu.getStudentName()+" 学号:"+stu.getStudentId()); } } }
迭代器的代码实现
public class IteratorDemo { public static void main(String[] args) { Collection<String> coll = new ArrayList<String>(); coll.add("abc1"); coll.add("abc2"); coll.add("abc3"); coll.add("abc4"); //迭代器,对集合ArrayList中的元素进行取出 //调用集合的方法iterator()获取出,Iterator接口的实现类的对象 Iterator<String> it = coll.iterator(); //接口实现类对象,调用方法hasNext()判断集合中是否有元素 //boolean b = it.hasNext(); //System.out.println(b); //接口的实现类对象,调用方法next()取出集合中的元素 //String s = it.next(); //System.out.println(s); //迭代是反复内容,使用循环实现,循环的条件,集合中没元素, hasNext()返回了false while(it.hasNext()){ String s = it.next(); System.out.println(s); } } }