概述
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()
: 把集合中的元素,存储到数组中。
迭代器
Iterator
主要用于迭代访问(即遍历)Collection
中的元素,位于java.util.Iterator
。
代码实例
点击查看代码
public class IteratorDemo {
public static void main(String[] args) {
// 使用多态方式 创建对象
Collection coll = new ArrayList();
// 添加元素到集合
coll.add("串串星人");
coll.add("吐槽星人");
coll.add("汪星人");
//遍历
//使用迭代器 遍历 每个集合对象都有自己的迭代器
Iterator it = coll.iterator();
// 泛型指的是 迭代出 元素的数据类型
while(it.hasNext()){ //判断是否有迭代元素
String s = it.next();//获取迭代出的元素
System.out.println(s);
}
}
}
增强for
增强for循环(也称for each循环)是JDK1.5 以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能 对集合中的元素进行增删 操作。
int[] arr = {3,5,6,87};
//使用增强for遍历数组
for(int a : arr){//a代表数组中的每个元素
System.out.println(a);
}
注意: 目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现。
注意点
虽然集合可以存储任何类型的对象,但是取出时会遇到类型转换异常;如果一开始限定集合存储的类型就不会出现这种情况。参考如下:
点击查看代码
//不指定存储类型;取出时强转引发运行时 ClassCastException
public class GenericDemo {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("abc");
coll.add("itcast");
coll.add(5);//由于集合没有做任何限定,任何类型都可以给其中存放
Iterator it = coll.iterator();
while(it.hasNext()){
//需要打印每个字符串的长度,就要把迭代出来的对象转成String类型
String str = (String) it.next();
System.out.println(str.length());
}
}
}
//指定存储类型,可以正常运行
public class GenericDemo2 {
public static void main(String[] args) {
Collection list = new ArrayList();
list.add("abc");
list.add("itcast");
// list.add(5);//当集合明确类型后,存放类型不一致就会编译报错
// 集合已经明确具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样会知道具体遍历元素类型
Iterator it = list.iterator();
while(it.hasNext()){
String str = it.next();
//当使用Iterator控制元素类型后,就不需要强转了。获取到的元素直接就是String类型
System.out.println(str.length());
}
}
}
泛型
泛型类
//定义
public class MyGenericClass {
//没有MVP类型,在这里代表未知的一种数据类型 未来传递什么就是什么类型
private MVP mvp;
public void setMVP(MVP mvp) {
this.mvp = mvp;
}
public MVP getMVP() {
return mvp;
}
}
//使用
public class GenericClassDemo {
public static void main(String[] args) {
// 创建一个泛型为String的类
MyGenericClass my = new MyGenericClass();
// 调用setMVP
my.setMVP("大胡子登登");
// 调用getMVP
String mvp = my.getMVP();
System.out.println(mvp);
//创建一个泛型为Integer的类
MyGenericClass my2 = new MyGenericClass();
my2.setMVP(123);
Integer mvp2 = my2.getMVP();
}
}
泛型方法
//定义
public class MyGenericMethod {
public void show(MVP mvp) {
System.out.println(mvp.getClass());
}
public MVP show2(MVP mvp) {
return mvp;
}
}
//使用
public class GenericMethodDemo {
public static void main(String[] args) {
// 创建对象
MyGenericMethod mm = new MyGenericMethod();
// 演示看方法提示
mm.show("aaa");
mm.show(123);
mm.show(12.45);
}
}
泛型接口
//定义
public interface MyGenericInterface{
public abstract void add(E e);
public abstract E getE();
}
//使用
public class MyImp1 implements MyGenericInterface {
@Override
public void add(String e) {
// 省略...
}
@Override
public String getE() {
return null;
}
}
泛型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?> 表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
例:
public static void main(String[] args) {
Collection list1 = new ArrayList();
getElement(list1);
Collection list2 = new ArrayList();
getElement(list2);
}
public static void getElement(Collection<?> coll){}
//?代表可以接收任意类型
注意: 泛型不存在继承关系 Collection list = new ArrayList();这种是错误的。
通配符高级使用----受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限 和下限 。
泛型的上限 :
格式 : 类型名称 <? extends 类 > 对象名称
意义 : 只能接收该类型及其子类
泛型的下限 :
格式 : 类型名称 <? super 类 > 对象名称
意义 : 只能接收该类型及其父类型
点击查看代码
public static void main(String[] args) {
Collection list1 = new ArrayList();
Collection list2 = new ArrayList();
Collection list3 = new ArrayList();
Collection list4 = new ArrayList();
getElement(list1);//Integer是number子类,符合上限
getElement(list2);//报错,string和number不相关
getElement(list3);//是number类型
getElement(list4);//报错,object是父类,超出上限
getElement2(list1);//报错,超出下限,Inteher是number子类
getElement2(list2);//报错,无关类型
getElement2(list3);//正好是number
getElement2(list4);//object是number父类,符合下限
}
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}
List
概述
继承自Collection
接口,在List集合中允许出现重复的元素;并且元素有序;带有索引,可以通过索引操作元素(类比数组的下标)。
常用方法
List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:
public void add(int index(可选参数), E element)
: 将指定的元素,添加到该集合中的指定位置上。
public E get(int index)
:返回集合中指定位置的元素。
public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。
public E set(int index, E element)
:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
子类1:ArraryList
java.util.ArrayList
集合数据存储的结构是数组 结构。元素增删慢,查找快 ,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList
是最常用的集合。
子类2:LinkedList
java.util.LinkedList
集合数据存储的结构是循环链表 结构。方便元素添加、删除 的集合。
常用方法(了解)
public void addFirst(E e)
:将指定元素插入此列表的开头。
public void addLast(E e)
:将指定元素添加到此列表的结尾。
public E getFirst()
:返回此列表的第一个元素。
public E getLast()
:返回此列表的最后一个元素。
public E removeFirst()
:移除并返回此列表的第一个元素。
public E removeLast()
:移除并返回此列表的最后一个元素。
public E pop()
:从此列表所表示的堆栈处弹出一个元素。
public void push(E e)
:将元素推入此列表所表示的堆栈。
public boolean isEmpty()
:如果列表不包含元素,则返回true。
Set
概述
继承自Collection
接口;存储元素不允许重复;元素无序。
取出元素的方式可以采用:迭代器、增强for。
HashSet
概述
java.util.HashSet
底层的实现其实是一个java.util.HashMap
支持。
HashSet
是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找 性能。保证元素唯一性的方式依赖于:hashCode
与equals
方法。
HashSet存储数据的结构(哈希表)
在JDK1.8 之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。
在JDK1.8 中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
哈希表存储流程
存储自定义对象
如果我们往集合中存放自定义的对象 ,那么保证其唯一,就必须复写hashCode和equals方法 建立属于当前对象的比较方式。
点击查看代码
//自定义student
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 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);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
//执行
public class HashSetDemo2 {
public static void main(String[] args) {
//创建集合对象 该集合中存储 Student类型对象
HashSet stuSet = new HashSet();
//存储
Student stu = new Student("于谦", 43);
stuSet.add(stu);
stuSet.add(new Student("郭德纲", 44));
stuSet.add(new Student("于谦", 43));
stuSet.add(new Student("郭麒麟", 23));
stuSet.add(stu);
for (Student stu2 : stuSet) {
System.out.println(stu2);
}
}
}
//执行结果:
Student [name=郭德纲, age=44]
Student [name=于谦, age=43]
Student [name=郭麒麟, age=23]
子类LinkedHashSet
HashSet下面有一个子类java.util.LinkedHashSet
,它是链表和哈希表组合 的一个数据存储结构。
点击查看代码
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set set = new LinkedHashSet();
set.add("bbb");
set.add("aaa");
set.add("abc");
set.add("bbc");
Iterator it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
结果:
bbb
aaa
abc
bbc
Collections工具类
java.utils.Collections
是集合工具类,用来对集合进行操作。
常用方法
public static boolean addAll(Collection c, T... elements)
:往集合中添加一些元素。
public static void shuffle(List<?> list) 打乱顺序
:打乱集合顺序。
public static void sort(List list)
:将集合中元素按照默认 规则排序。
public static void sort(List list,Comparator<? super T> )
:将集合中元素按照指定规则排序 。
Comparator比较器
排序:在JAVA中提供了两种比较实现的方式,一种是比较死板的采用java.lang.Comparable
接口去实现,一种是灵活的当我需要做排序的时候在去选择的java.util.Comparator
接口完成。
比较规则: public int compare(String o1, String o2)
:比较其两个参数的顺序。
两个对象比较的结果有三种:大于,等于,小于。
如果要按照升序排序:
o1 小于o2,返回(负数);相等返回0;o1大于o2返回(正数)
如果要按照降序排序:
o1 小于o2,返回(正数);相等返回0;o1大于o2返回(负数)
点击查看代码
public class CollectionsDemo3 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法 按照第一个单词的降序
Collections.sort(list, new Comparator() {
@Override
public int compare(String o1, String o2) {
//首字母按照字典序,降序
return o2.charAt(0) - o1.charAt(0);
}
});
System.out.println(list);
}
}
//结果
[sba, nba, cba, aba]
***
简述Comparable和Comparator两个接口的区别。
Comparable: 强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
Comparator: 强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
Comparable和Comparator用法
Comparable
点击查看代码
//自定义Student
public class Student implements Comparable{
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) {
return this.age-o.age;//升序
}
}
//测试
public class Demo {
public static void main(String[] args) {
// 创建四个学生对象 存储到集合中
ArrayList list = new ArrayList();
list.add(new Student("rose",18));
list.add(new Student("jack",16));
list.add(new Student("abc",16));
list.add(new Student("ace",17));
list.add(new Student("mark",16));
/*
让学生 按照年龄排序 升序
*/
Collections.sort(list);//要求 该list中元素类型 必须实现比较器Comparable接口
for (Student student : list) {
System.out.println(student);
}
}
}
结果
Student{name='jack', age=16}
Student{name='abc', age=16}
Student{name='mark', age=16}
Student{name='ace', age=17}
Student{name='rose', age=18}
Comparator
点击查看代码
//无需在类中实现Comparable,直接在main中
Collections.sort(list, new Comparator() {
@Override
public int compare(Student o1, Student o2) {
return o2.getAge()-o1.getAge();//以学生的年龄降序
}
});
//两个规则,年龄降序,相等则按姓名升序
Collections.sort(list, new Comparator() {
@Override
public int compare(Student o1, Student o2) {
// 年龄降序
int result = o2.getAge()-o1.getAge();//年龄降序
if(result==0){//第一个规则判断完了 下一个规则 姓名的首字母 升序
result = o1.getName().charAt(0)-o2.getName().charAt(0);
}
return result;
}
});
//结果
Student{name='rose', age=18}
Student{name='ace', age=17}
Student{name='abc', age=16}
Student{name='jack', age=16}
Student{name='mark', age=16}
***
参考来自黑马,侵删。