引入集合的目的:在使用数组存储元素时必须确定数组的长度,即数组存储元素的个数是固定的,这在实际运用时有十分大的局限性,因此引入集合可以结局这个问题。
集合的概念:JAVA API所提供的一系列类的实例,可以用于动态存放多个对象。集合类位于java.util包中,
特点: 长度不固定,只能存储引用类型的对象
集合的大致框架
其中
Collection接口存储一组不唯一的对象;
List接口存储一组不唯一的,有序的对象;Set接口存储一组唯一的、不可重复的对象
Map集合存储一组键值对象。
一、List接口的实现类之一 —— ArrayList集合(有时间实现一下)
ArrayList有点类似于数组,不过在存储元素时更加灵活,在添加元素时不必指明集合的长度,底层实现是是通过ensureCapacity来增加其容量。
构造方法
ArrayList() : 构造一个初始容量为 10 的空集合;
ArrayList(Collection< ? extends E> c) :构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection的迭代器返回它们的顺序排列的;
ArrayList(int initialCapacity):构造一个具有指定初始容量的空列表;
一些重要方法
boolean add(E e) : 将元素添加到集合尾部;
void add(int index,E e):将元素插入到指定位置;
boolean contains(Object o): 判断集合中是否包含所给元素;
E get(int index): 返回此列表中指定位置的元素;
E remove(int index): 移除集合中指定位置上的元素;
int size(): 返回该集合的长度
Object[] toArray():按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;
简单使用示例
package list;
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("小花");
list.add("小红");
list.add("小黑");
list.add("小绿");
list.add("小名");
list.add(2,"小黄");
System.out.println(list.contains("大花"));
//利用for循环遍历list元素
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i)+" ");
}
list.remove("小绿");
//String[] str = (String[]) list.toArray();
}
}
二、List集合的实现类之二 —— LinkedList(有时间去实现一下)
优点:插入或删除快效率高
缺点:查找速度慢
三、Collection工具类Collection是集合的工具类,其中提供了一系列的静态方法,用于操作集合的一系列静态方法。
package collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo {
public static <E> void showList(List<E> list){
for(E e : list){
System.out.print(e+" ");
}
System.out.println();
System.out.println("**************");
}
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
//该方法可以实现向集合中添加元素
Collections.addAll(list,"瓜皮","智障","神经病","妖刀村正","天域","恍惚","三神器","年套");
CollectionsDemo.showList(list);
//shuffle(xxx)方法将list集合中的数据顺序打乱
Collections.shuffle(list);
CollectionsDemo.showList(list);
//reverse()方法将打乱的list集合中的数据逆序输出
Collections.reverse(list);
CollectionsDemo.showList(list);
}
}
四、迭代器的使用(Iterator)
Iterator是专门的迭代输出接口,迭代输出的意思是将元素进行判断,判断是否有内容,如果有内容就将内容取出。
Iterator对象成为迭代器,用以方便的实现对集合内容元素的遍历操作。
集合能用迭代器遍历的原因:所有实现了Collections接口的集合类都有一个iterator()方法用以返回一个实现了Iterator接口的对象
eg: Iterator it = coll.iterator();
while(it.hasNext()){
it.next();
}
Iterator接口定义了如下方法:
boolean hasNext(): 判断游标的下一个是否还有元素;
Object next(): 返回游标右边的元素并将游标移动到下一个位置;
遍历实例如下:
五、泛型的使用
泛型是对Java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样,即使用泛型之后可以在使用泛型类时指定类型参数的类型。
泛型的好处:
1.解决类型安全的问题(运行时出现的ClassCastException异常);
2.当我们从集合中获取值时不必进行强制类型转换;
3.使用泛型之后,我们可以指定加入集合中对象的类型,这样,在加入错误类型的对象时在编译期间编译器会报错,增加了程序的安全性和可读性;
泛型类设置如下:
关于受限泛型:
1.设置上限
类型名称<? entends 上限类> :只能接收上限类对象或其子类对象;
2.设置下限
类名称<? super 下限类>:接收下限类对象或其父类对象
注:若定义泛型类,可以将?设置为泛型标识
六、Set集合
Set集合中的元素为不可重复的
HashSet:散列存储;
TreeSet:有序存放(按指定顺序存放);
6.1 HashSet(重点讨论存储原理)
HashSet的存储原理:在调用add()方法时,根据每个对象的哈希码值(自动调用hashCode())用固定的算法算出它的存储索引,把对象存放在一个叫散列表的相应位置中;
若对应位置没有其他元素,就只需要直接存入;
若该位置有元素了,会将新对象跟该位置的所有对象进行比较,,以查看是否已经存在该元素,若存在了就不存放了,若不存在就存放新元素(比较的时候是用equals()方法进行比较的)
若若存储的对象类没有hashCode和equals方法,便自动调用Object类中的这俩个方法
比如存储学生类对象:
package set.hashset;
public class Student {
private String name;
private String sex;
private int age;
public Student(){
}
public Student(String name,String sex,int age){
this.name = name;
this.sex = sex;
this.age = age;
}
//HashSet实现元素的不重复的方法是:
/*
* 1.若对应位置的哈希码值(调用hashcode()方法)用固定的算法算出他的存储索引值对应的位置如果没有
* 元素时,就直接把该元素放进去,调用的hashcode方法跟hashset存储的对象有关系,若该对象重写了hashcode方法
* 则调用的是对象所属类的hashcode方法,否则调用Object的hashcode的方法
* 2.若比较的hashcode值对应的索引处已经有元素了,则比较存储对象和该元素是否为同一对象,若一样就不存放了,若不一样就存储,
* 比较的方法是调用equals方法,若对象所属类重写了equals方法则调用的是它的equals方法,否则依然调用Object类的equals方法
* 以上调用的hashcode和equals方法都是对象自动调用的!!!!!!!!
*/
//重写hashcode方法
@Override
public int hashCode() {
return (this.age+3)*2;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
Student stu = (Student)obj;
if(this.name.equals(stu.name) && this.age==stu.age && this.sex.equals(stu.sex)){
return true;
}
return false;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
}
存储时候用hashSet存储:
package set.hashset;
import java.util.HashSet;
import java.util.Iterator;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<Student> hs = new HashSet<>();
hs.add(new Student("小红","女",20));
hs.add(new Student("小飞","男",18));
hs.add(new Student("小刚","男",28));
hs.add(new Student("小天","男",20));
hs.add(new Student("小红","女",20));
hs.add(new Student("小红","女",20));
hs.add(new Student("小红","女",20));
hs.add(new Student("小红","女",20));
//用迭代器遍历hashset集合中的内容
Iterator<Student> it = hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
遍历结果为:
七、TreeSet集合(重点讨论存储原理)
TreeSet集合可以对加入其中的元素进行排序,前提是必须指定排序规则,即TreeSet所存储的对象的类必须实现Comparable接口,重写compareTo()方法
TreeSet的重要构造方法:
public TreeSet() : 若使用无参构造实例化集合对象,则加入到TreeSet集合的对象所属的类必须实现Comparable接口,重写
int compareTo (T o)方法,并在方法中编写排序规则,compareTo方法返回值只有正整数,负整数和0;同时在比较排序的过程中已经进行去重操作了
实例如下(用TreeSet类存储Rice类对象):
package set.treeset;
//对米饭类对象进行排序
public class Rice implements Comparable<Rice>{
private String name;
private int score; //根据口味打的分
private int price; //米饭价格
public Rice(){
}
public Rice(String name,int score,int price){
this.name = name;
this.score = score;
this.price = price;
}
@Override //升序排列,实现Comparable接口,重写compareTo方法
public int compareTo(Rice r) {
if(this.score > r.score){
return 1;
}else if(this.score < r.score){
return -1;
}else{
if(this.price > r.price){
return 1;
}else if(this.price < r.price){
return -1;
}else{
return this.name.compareTo(r.name);
}
}
}
@Override
public String toString() {
return "Rice [name=" + name + ", score=" + score + ", price=" + price
+ "]";
}
}
存储:
package set.treeset;
import java.util.TreeSet;
public class TreeTreeSet {
public static void main(String[] args) {
TreeSet<Rice> tr = new TreeSet<>();
tr.add(new Rice("排骨饭",8,18));
tr.add(new Rice("西红柿鸡蛋饭",5,12));
tr.add(new Rice("鱼香肉丝饭",8,15));
tr.add(new Rice("竹笋饭",9,18));
tr.add(new Rice("瓜皮饭",8,18));
tr.add(new Rice("排骨饭",8,18));
for(Rice r : tr){
System.out.println(r);
}
}
}
遍历结果为:
集合的概念十分重要,值得深挖。