Collection集合
- 集合工具存放在java.util包中。
- 集合按照其存储结构分为两大类:单列集合Collection和双列集合Map。
- 集合和数组的区别:数组的长度是固定的。集合的长度是可变的;数组中存储的是同一类型的元素,可以存储基本数据类型值,而集合存储的是对象且对象的类型可以不一致。
- Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是
java.util.List
和java.util.Set
。其中,List
的特点是元素有序、元素可重复。Set
的特点是元素无序,而且不可重复。List
接口的主要实现类有java.util.ArrayList
和java.util.LinkedList
,Set
接口的主要实现类有java.util.HashSet
和java.util.TreeSet
。
Collection 常用方法
Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:
public boolean add(E e)
: 把给定的对象添加到当前集合中 。public void clear()
:清空集合中所有的元素。public boolean remove(E e)
: 把给定的对象在当前集合中删除。public boolean contains(E e)
: 判断当前集合中是否包含给定的对象。public boolean isEmpty()
: 判断当前集合是否为空。public int size()
: 返回集合中元素的个数。public Object[] toArray()
: 把集合中的元素,存储到数组中。
import java.util.ArrayList;
import java.util.Collection;
public class Collectiontest {
public static void main(String[] args) {
Collection<String> col = new ArrayList<String>();
//添加元素
col.add("a");
col.add("b");
System.out.println(col);
//查看是否包含某个元素
System.out.println(col.contains("a"));//true
System.out.println(col.contains("b"));//false
//删除元素
col.remove("a");
System.out.println(col.contains("a"));//false
//查看元素数量
System.out.println("集合中有"+col.size()+"个元素");
//把集合转换成数组
String[] strlist = col.toArray();
//清空集合
col.clear();
//判断集合是否为空
System.out.println(col.isEmpty());
}
}
遍历方法
Iterator接口
获取集合的迭代器:
public Iterator iterator()
: 获取集合对应的迭代器,用来遍历集合中的元素。- 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式称为迭代。
Iterator接口的常用方法如下:
public E next()
:返回迭代的下一个元素。public boolean hasNext()
:如果仍有元素可以迭代,则返回 true。
public class Iteratortest {
public static void main(String[] args) {
Collection<String> col = new ArrayList<String>();
col.add("a");
col.add("b");
col.add("c");
//使用迭代器遍历
Iterator<String> iter = col.iterator();
while(iter.hasNext()){ //判断是否有迭代元素
String s = iter.next();//获取迭代出的元素
System.out.println(s);
}
}
}
增强for循环
增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
遍历数组:
public class fortest1 {
public static void main(String[] args) {
String[] cxk = {"唱","跳","rap","篮球"};
//使用增强for遍历数组
for(String i : cxk){//i代表数组中的每个元素
System.out.println(i);
}
}
}
遍历集合:
public class fortest2 {
public static void main(String[] args) {
Collection<String> cxk = new ArrayList<String>();
cxk.add("唱");
cxk.add("跳");
cxk.add("rap");
cxk.add("篮球");
//使用增强for遍历
for(String i : cxk){
System.out.println(i);
}
}
}
tips: 新for循环必须有被遍历的目标。目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现,不能对元素进行删增操作。
Collection常用子类
List接口
特点:元素存取有序;带有索引;元素可以重复。
接口方法:
public void add(int index, E element)
: 将指定的元素,添加到该集合中的指定位置上。public E get(int index)
:返回集合中指定位置的元素。public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。public E set(int index, E element)
:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。、
子类:
- ArrayList
数据存储的结构是数组结构;元素增删慢,查找快。常用。 - LinkedList
数据存储的结构是链表结构;方便添加或删除元素。有很多操作首尾元素的方法,如addFirst()、addLast()、push()、pop()等。
Set接口
特点:元素无序,元素无重复。
子类:
- HashSet
根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于hashCode
与equals
方法。在存储自定义对象时,要重写这两个方法。 - LinkedHashSet
元素有序。
Collections类
集合工具类,包含一些对Collection集合进行操作的方法。
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。public static void shuffle(List<?> list)
:打乱集合顺序。public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序(数值类型和字符串类型默认的是升序)。public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。规定的比较器(Comparator)泛型的界限,只能是T或者T的父类。
Comparator和Comparable接口
Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。一些基本数据类型的包装类已经实现了compareTo()方法。如果要按照不同的规则排序,不适合经常修改compareTo()方法。
Comparator:强行对对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
例子:
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;
}
}
测试:
public class comparetest {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("a",10));
list.add(new Student("b",11));
list.add(new Student("c",12));
//按照年龄升序排序
Collections.sort(list);
for (Student student : list) {
System.out.println(student.getName());
}
}
}
此时sort方法会报错,因为没有给Student类排序规则。我们有两种方法解决这个问题,一是让Student实现Comparable接口,重写compareTo方法,二是编写一个自定义的比较器类实现Comparator接口,重写compare方法。
实现Comparable接口:
public class Student implements Comparable<Student>{
....
@Override
public int compareTo(Student o) {
return this.age-o.age;//升序(返回负数表示排在o之前,正数表示在o之后)
}
}
再次运行上述的测试代码,输出结果依次是:a、b、c。
实现Comparator接口:
public class AgeComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
//返回负数,o1在o2之前;返回正数o1在o2之后
return o1.getAge()-o2.getAge();
}
}
执行以下测试代码:
public class comparetest {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("a",10));
list.add(new Student("b",11));
list.add(new Student("c",12));
//按照年龄升序排序,给sort方法第二个参数传入一个比较器对象
Collections.sort(list,new AgeComparator());
for (Student student : list) {
System.out.println(student.getName());
}
}
}
效果和上面一样。也可以直接在参数里构件比较器,如下:
public class comparetest {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("a",10));
list.add(new Student("b",11));
list.add(new Student("c",12));
//按照年龄升序排序,给sort方法第二个参数传入一个比较器对象
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});
for (Student student : list) {
System.out.println(student.getName());
}
}
}
tips:如果两种接口都实现了,在调用sort方法时如果传入了比较器,则以比较器的规则进行排序。