集合---单列集合Collection
集合和数组的区别
- 数组可以存任何数据类型,集合只能存引用数据类型
- 如果集合想存基本数据类型,泛型中要定义它们的包装类。
- 数组的长度不可变,集合的长度可变
集合的体系结构
Collection集合
- 是单列集合的顶层接口
- 它提供更具体的子接口List和Set实现
Collection接口中提供的常用方法方法:
1 Collection<String> collection = new ArrayList<>(); 2 collection.add("aaa");//向集合中添加元素 3 boolean b = collection.remove("aaa");//删除集合中的元素并返回布尔型结果true表示删除成功,false表示删除失败 4 int size = collection.size();//返回集合已存数据的个数 5 boolean b1 = collection.removeIf((String s) -> { 6 return s.length()==2; 7 });//根据条件删除元素 8 boolean result = collection.contains("aaa");//判断集合中是否有指定元素 9 collection.clear();//清除集合内所有元素
Iterator迭代器(集合特有)
- 单列集合可以直接使用迭代器
- 创建一个迭代器对象:Iterator<String> it = list.iterator();默认指向集合第一个索引
- boolean hasNext(); 判断集合索引处是否含有元素
- next(); 取出索引处元素,并将迭代器指向集合的索引位置向下推进一次
public static void main(String[] args) { ArrayList<String> list=new ArrayList<>(); list.add("sss"); list.add("sss"); list.add("sss"); list.add("sss"); list.add("sss"); list.add("sss"); list.add("sss"); Iterator<String> it = list.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); }
增强for
- 格式:for(Object o:集合或数组名){o就是从集合或数组中的每一个第三方中间变量,可对其进行操作但修改不会改变原集合或者数组}
- 实现Iterable接口的类才可以使用迭代器和增强for(单列集合Collection实现了Iterable,双列集合Map没有实现)
- 在迭代器中不能通过集合对象增删元素,不然会发生并发错误
下面先讲单列集合:
List(有序,有索引,可重复)
list集合的常用方法:
-
public static void main(String[] args) { List<String> list=new ArrayList<>();//多态形式,只能有List中的方法 list.add("aaa");// list.add("aaa"); list.add("aaa"); list.add("aaa"); list.add("aaa"); list.add(3,"ooo");//在制定索引增加元素 String s1 = list.get(0);//在制定索引获得制定索引元素 String remove = list.remove(1);//删除指定索引元素 String s3 = list.set(0, "nnn");//设置指定索引元素 }
ArrayList(底层是数组查询快,增删慢)
1.Arraylist第的底层结构是数组,在ArrayList创建对象的时候,默认长度是0,也就是空集合,但是在add();方法执行后会把集合长度变为10,所以我们一般认为ArrayList集合的默认长度是10,当添加的元素的格式超过10的时候,会自动创建一个新的集合,长度为原来集合的1.5倍,然后把原来集合的所有数据全部赋值给新的集合。
2.size
size是集合创建时的底层变量,它的默认值是0,当每次使用add();方法向集合中添加元素的时候,size就会+1;指向下一个将要被添加元素的索引,所以size也可以理解为集合中当前拥有的元素个数。
LinkedList
1.LinkedList(底层结构是链表,查询慢,增删快)
public static void main(String[] args) { LinkedList<String> list = new LinkedList<>(); list.addFirst("aaa");//添加元素到头部 list.add("sss"); list.addLast("zzz");//添加元素到尾部 list.removeFirst();//删除头部元素 list.removeLast();//删除尾部元素 list.getFirst();//获得头部元素 list.getLast();//获得尾部元素 }
Set(不可重复)
Set集合的特点
- 可以去除重复
- 存取顺序不一致
- 没有带索引的方法,所以不能用普通for遍历也不能通过索引来获取或者删除Set集合里面的元素
TreeSet集合的特点(底层是红黑树)
- 不重复
- 没有带索引的方法
- 可以将元素按照规则进行排序
TreeSet的自然排序(自定义对象要实现Comparable接口)
1 package com.heima.test; 2 3 import java.util.TreeSet; 4 5 public class TreeSetTest { 6 public static void main(String[] args) { 7 TreeSet<Student> treeSet=new TreeSet<>(); 8 Student student1=new Student("xiaoming",22); 9 Student student2=new Student("wanggang",23); 10 Student student3=new Student("liuneng",25); 11 Student student4=new Student("zhanosi",21); 12 Student student5=new Student("zhulei",22); 13 treeSet.add(student1); 14 treeSet.add(student2); 15 treeSet.add(student3); 16 treeSet.add(student4); 17 treeSet.add(student5); 18 treeSet.add(student5);//重复添加测试 19 System.out.println(treeSet); 20 21 22 23 24 25 26 27 28 29 30 } 31 }
package com.heima.test; public class Student implements Comparable<Student> {//实现并重写comparato方法 private String name; private int age; public Student() { } public Student(String name, int age) { 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 compareTo(Student o) { int result = this.age - o.age;//首先按照年龄从小到大排序 return result == 0 ? this.name.compareTo(o.name) : result;//在年龄相等的情况下按照姓名字母的字典比较方法排序 } }
TreeSet的Comparator比较器排序(使用TreeSet的带参构造)
代码如下:
package com.heima.test; import java.util.Comparator; import java.util.TreeSet; public class TreeSetTest { public static void main(String[] args) { TreeSet<Student> treeSet=new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { int result = o1.getAge() - o2.getAge(); return result==0?o1.getName().compareTo(o2.getName()):result;//匿名内部类的方式重写 } }); Student student1=new Student("xiaoming",22); Student student2=new Student("wanggang",23); Student student3=new Student("liuneng",25); Student student4=new Student("zhanosi",21); Student student5=new Student("zhulei",22); treeSet.add(student1); treeSet.add(student2); treeSet.add(student3); treeSet.add(student4); treeSet.add(student5); treeSet.add(student5);//重复添加测试 System.out.println(treeSet); } }
两种比较方式的选择,在自然排序不满足需求时,可以选择比较排序
HashSet
-
底层数据结构是哈希表
- 不能保证存储和取出的顺序完全一致
- 没有索引
- 不重复
HashCode(哈希值):是JDK根据对象的地址或者属性值(要经过方法重写)算出来的int类型的整数
Object类中的public inthashcode();方法根据地址值计算出来哈希值,HashSet集合存储对象是根据哈希值和集合长度计算出来的值进行存储的。
存数据时要重写hashCode方法
代码如下:
package com.heima.test; import java.util.Comparator; import java.util.HashSet; import java.util.TreeSet; public class HashSetTest { public static void main(String[] args) { HashSet<Student> hashSet=new HashSet<>(); Student student1=new Student("haha",23); Student student2=new Student("haha",24); Student student3=new Student("haha",25); Student student4=new Student("haha",26); Student student5=new Student("haha",23);//重复测试 hashSet.add(student1); hashSet.add(student2); hashSet.add(student3); hashSet.add(student4); hashSet.add(student5); System.out.println(hashSet); } }
package com.heima.test; public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { 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 boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (age != student.age) return false; return name != null ? name.equals(student.name) : student.name == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0;//重写HashCode方法 result = 31 * result + age; return result; } }
迎风少年