集合和数组的区别
- 数组可以存任何数据类型,集合只能存引用数据类型
- 如果集合想存基本数据类型,泛型中要定义它们的包装类。
- 数组的长度不可变,集合的长度可变
集合的体系结构
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;
}
}
迎风少年