所有的集合类和集合接口都在java.util包下。
一类是单个方式存储元素: 单个方式存储元素,这一类集合中超级父接口:java.util.Collection; 一类是以键值对儿的方式存储元素 以键值对的方式存储元素,这一类集合中超级父接口:java.util.Map;
Collection 是 List 和 Set 的父接口
boolean add(E e) 向集合中添加元素
int size();获取集合中的元素个数
void clear();清空集合
boolean contains(Object o) 判断当前集合是否含有o元素
boolean remove(Object o) 删除集合中的元素
boolean isEmpty() 判断集合是否为空
Object[] toArray() 把集合转换为数组
示例代码(1):
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionText {
public static void main(String[] args) {
Collection collection = new ArrayList();
//向集合中添加元素
boolean b1 = collection.add(100);
boolean b2 = collection.add("你好,java");
boolean b3 = collection.add("中国");
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
//获取集合中的元素个数
int i1 = collection.size();
System.out.println(i1);
//collection.clear();
//System.out.println(collection.size());
boolean b = collection.contains(100);
System.out.println(b);
//删除集合中的元素
collection.remove("中国");
System.out.println(collection.size());
//判断集合是否为空
System.out.println(collection.isEmpty());
collection.clear();
System.out.println(collection.isEmpty());
collection.add("我");
collection.add("是");
collection.add("中");
collection.add("国");
collection.add("人");
//转换为数组
Object[] objects=collection.toArray();
for(int i=0;i<objects.length;i++){
Object o=objects[i];
System.out.println(o);
}
System.out.println(Arrays.toString(objects));
}
}
运行结果:
true
true
true
3
true
2
false
true
我
是
中
国
人
[我, 是, 中, 国, 人]
Process finished with exit code 0
注:Collection在使用泛型之前,可存放Object的所有子类,在使用泛型之后,只能存某个具体的类型。
迭代器是一个对象
第一步:获取集合对象的迭代器对象 第二部:通过获取的迭代器对象进行迭代(遍历)
boolean hasNext()
; true:有元素迭代 false:无元素迭代E next() ;
返回迭代的下一个元素
示例代码(2):
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionText01 {
public static void main(String[] args) {
//创建集合
Collection c1=new ArrayList();
c1.add(100);
c1.add("abc");
c1.add("def");
c1.add(new Object());
//第一步:获取集合对象的迭代器对象iterator
Iterator it=c1.iterator();
//第二步通过获取的迭代器对象进行集合遍历/迭代。
while (it.hasNext()){
Object obj=it.next();
System.out.println(obj);
}
}
}
运行结果:
100
abc
def
java.lang.Object@723279cf
1.集合结果发生改变,迭代器需要重新获取 2.迭代过程中不能调用remove()方法删除元素,会出现异常(ConcurrentModificationException) 3.迭代元素的过程中使用迭代器的remove()方法删除元素
示例代码(3):
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionText05 {
public static void main(String[] args) {
Collection c=new ArrayList();
//ConcurrentModificationException异常!!!
//Iterator it=c.iterator();
c.add(1);
c.add(2);
c.add(3);
Iterator it=c.iterator();
while (it.hasNext()){
Object o=it.next();
// 没有更新迭代器
//c.remove();直接通过集合,没有通知迭代器(导致迭代器快照与原集合状态不同)
//更新迭代器 。
it.remove(); //删除的是迭代器指向的当前对象。
System.out.println(o);
}
System.out.println(c.size());
}
}
运行结果:
1
2
3
0
他们都是有顺序的,也就是放进去是什么顺序,取出来还是什么顺序,也就是基于线性存储,可以看作是一个可变数组
void add(int index, E element) 在列表中指定的位置上插入指定的元素
E get(int index) 根据下标获取元素
int indexOf(Object o) 返回此列表中指定元素的第一个出现的索引
int lastIndexOf(Object o) 返回此列表中指定元素的最后一个发生的索引
E remove(int index) 移除此列表中指定下标的元素
E set(int index, E element) 用指定元素替换此列表中指定位置的元素
示例代码(4):
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListText01 {
public static void main(String[] args) {
//创建list类型集合
List list=new ArrayList();
//添加元素,将指定的元素到这个列表的末尾
list.add("a");
list.add("b");
list.add("c");
//在列表中指定的位置上插入指定的元素(效率低!!!)
list.add(1,"ooo");
//迭代器
Iterator it=list.iterator();
while(it.hasNext()){
Object o=it.next();
System.out.println(o);
}
System.out.println("=================================");
//根据下标获取元素
Object o=list.get(0);
System.out.println(o);
//list集合特有的遍历方法!!
for(int i=0;i<list.size();i++){
System.out.println( list.get(i));
}
// 返回此列表中指定元素的第一个出现的索引
System.out.println(list.indexOf("b"));
//返回此列表中指定元素的最后一个发生的索引
System.out.println(list.lastIndexOf("c"));
System.out.println("=============================");
//移除此列表中指定位置的元素
list.remove(1);
System.out.println(list.size());//3
//用指定元素替换此列表中指定位置的元素
list.set(0,"n");
System.out.println(list.get(0));
}
}
运行结果:
a
ooo
b
c
==============================
a
a
ooo
b
c
2
3
=============================
3
n
ArrayList集合优化:尽可能少的扩容,数组扩容效率低。
优点:查询数据比较快,检索效率高 缺点:添加和删除数据比较慢,无法存大数据量(向数组末尾添加元素效率高)
示例代码(5):
import java.util.*;
public class ArrayListText01 {
public static void main(String[] args) {
//初始化容量为10
List list1=new ArrayList();
//初始化容量为20
List list2=new ArrayList(20);
Collection c=new ArrayList();
c.add("cccc");
c.add("bvncm");
c.add("mnkj");
Iterator it=c.iterator();
while (it.hasNext()){
Object o= it.next();
System.out.println(o);
}
}
}
运行结果:
cccc
bvncm
mnkj
优点:添加和删除数据比较快,随机增删效率高 缺点:查询数据比较慢,检索效率低。
优点: 1.集合中存储元素类型统一 2.集合中去除掉元素是泛型指定的类型,无需进行向下转型。 缺点:导致集合中元素缺乏多样性
List<String> list = new ArrayList<>();
类型自动推断!
示例代码(6):
自定义类:
class Animal{
public void run(){
System.out.println("动物在移动!!");
}
}
class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void fly(){
System.out.println("狗在飞");
}
}
测试类:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* jdk5.0之后的特性:泛型
*/
public class GenericText {
//使用泛型之前
public static void main(String[] args) {
List list = new ArrayList();
Cat cat = new Cat();
Dog dog = new Dog();
list.add(cat);
list.add(dog);
Iterator it = list.iterator();
while (it.hasNext()) {
Object o = it.next();
if (o instanceof Animal) {
((Animal) o).run();
}
}
}
}
运行结果:
动物在移动!!
动物在移动!!
测试类:
public class GenericText {
public static void main(String[] args) {
//使用泛型List<Animal>后,表示List集合只能存储Animal类型的元素
//泛型指定集合中存储的数据类型
List<Animal> list = new ArrayList<Animal>();
Cat cat = new Cat();
Dog dog = new Dog();
list.add(cat);
list.add(dog);
//表示迭代器迭代Animal类型
Iterator<Animal> it = list.iterator();
while (it.hasNext()) {
//使用泛型后,迭代器每一次返回的数据是Animal类型
Animal a = it.next();
//无需强转,直接调用
a.run();
if (a instanceof Cat) {
((Cat) a).catchMouse();
} else if (a instanceof Dog) {
((Dog) a).fly();
}
}
}
}
运行结果:
动物在移动!!
猫抓老鼠
动物在移动!!
狗在飞
一起找不同吧!!!!!
无序表示存进去是这个顺序,取出来就不一定是这个顺序了,另外Set集合中元素没有下标。Set集合中的元素还不能重复。
HashSet 中的数据是无序的不可重复的。HashSet 按照哈希算法存取数据的,具有非常好性能,它的工作原理是这样的,当向 HashSet 中插入数据的时候,他会调用对象的 hashCode 得到该对象的哈希码,然后根据哈希码计算出该对象插入到集合中的位置。
如果HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals方法比较true,但它们的hashCode方法返回的值不相等,HashSet将会把它们存储在不同位置,依然可以添加成功。 HashSet集合判断两个元素的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回值也相等。
特别是向 HashSet 或 HashMap 中加入数据时必须同时覆盖 equals 和 hashCode 方法,应该养成一种习惯覆盖 equals 的同时最好同时覆盖 hashCode
两个对象 equals 相等,那么它的 hashcode 相等 两个对象 equals 不相等,那么它的 hashcode 并不要求它不相等,但一般建议不相等 hashcode 相等不代表两个对象相等(采用 equals 比较)
示例代码(7):
自定义类:
public class Student {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类:
import java.util.HashSet;
import java.util.Set;
public class HashMapText02 {
public static void main(String[] args) {
Student s1 = new Student("zhangsan");
Student s2 = new Student("zhangsan");
System.out.println(s1.equals(s2));
//重写hashCode之前
System.out.println("s1hashCode值:" + s1.hashCode());
System.out.println("s2hashCode值:" + s2.hashCode());
Set<Student> set=new HashSet<>();
set.add(s1);
set.add(s2);
System.out.println(set.size());//2
}
}
运行结果:
false
s1hashCode值:284720968
s2hashCode值:122883338
2
自定义类:
public class Student {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//equals方法
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name);
}
//hashCode方法
public int hashCode() {
return Objects.hash(name);
}
}
测试类:
import java.util.HashSet;
import java.util.Set;
public class HashMapText02 {
public static void main(String[] args) {
Student s1 = new Student("zhangsan");
Student s2 = new Student("zhangsan");
System.out.println(s1.equals(s2));
//重写hashCode之后
System.out.println("s1hashCode值:" + s1.hashCode());
System.out.println("s2hashCode值:" + s2.hashCode());
Set<Student> set=new HashSet<>();
set.add(s1);
set.add(s2);
System.out.println(set.size());//1
}
}
运行结果:
true
s1hashCode值:-1432604525
s2hashCode值:-1432604525
1
找呀找呀,找不同。
第一种:Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,实现了该接口的类必须实现该方法,实现接口的类就可以比较大小了。当调用一个一个对象调用该方法与另一个对象进行比较obj1.compareTo(obj2)如果返回0表示两个对象相等;如果返回正整数则表明obj1大于obj2,如果是负整数则相反。 第二种:在构造TreeSet或TreeMap集合时给他一个比较器对象。比较规则自己写!!!
当比较规则不会发生改变时或比较规则只用一个时建议实现Comparable接口 当比较规则有多个,并且需要多个比较规则之间进行切换,建议使用与Comparator 编写比较器可以改变规则!!! Comparator区别符合OCT原则
示例代码(8):
import java.util.TreeSet;
public class TreeMapText01 {
public static void main(String[] args) {
//
TreeSet<String> ts=new TreeSet();
ts.add("zhangsan");
ts.add("wangwu");
ts.add("make");
ts.add("langlang");
for (String s: ts){
System.out.println(s);
}
System.out.println("=============================");
TreeSet<Integer> ts2=new TreeSet();
ts2.add(200);
ts2.add(300);
ts2.add(600);
ts2.add(14);
for (Integer i:ts2){
System.out.println(i);
}
}
}
运行结果:
langlang
make
wangwu
zhangsan
=============================
14
200
300
600
Process finished with exit code 0
从以上结果可以看出,String类和Integer类都实现了这个接口。 示例代码(9):
Customer类:
class Customer implements Comparable<Customer>{
int age;
public Customer(int age) {
this.age = age;
}
//需要在此方法写比较的逻辑,或者说出比较规则,按照什么进行比较!!
//比较规则自己定
public int compareTo(Customer o) {//c1.comperTo(c2);
//this是c1,o是c2
//c1与c2比较,就是this与c比较
// return this.age-o.age;
return o.age-this.age;
}
@Override
public String toString() {
return "Customer{" + "age=" + age + '}';
}
}
测试类:
import java.util.TreeSet;
public class TreeSetText03 {
public static void main(String[] args) {
Customer p = new Customer(23);
Customer p2 = new Customer(100);
Customer p3 = new Customer(30);
Customer p4 = new Customer(65);
Customer p5 = new Customer(46);
TreeSet<Customer> treeSet = new TreeSet<>();
treeSet.add(p);
treeSet.add(p2);
treeSet.add(p3);
treeSet.add(p4);
treeSet.add(p5);
for (Customer c : treeSet) {
System.out.println(c);
}
}
}
运行结果:
Customer{age=100}
Customer{age=65}
Customer{age=46}
Customer{age=30}
Customer{age=23}
示例代码(10):
WuGui类:
class WuGui {
int age;
public WuGui(int age) {
this.age = age;
}
@Override
public String toString() {
return "WuGui{" +
"age=" + age +
'}';
}
}
比较器:
//单独在这里编写一个比较器
//比较实现java.util.Comparator接口。(Comparable是java.lang包下的,Comparator接口是java.util包下)
class WuguiComparator implements Comparator<WuGui> {
public int compare(WuGui o1, WuGui o2) {
return o1.age - o2.age;
}
}
测试类:
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetText05 {
public static void main(String[] args) {
//创建TreeSet时,需要使用比较器
//TreeSet<WuGui> wuGuis=new TreeSet<>();这样不行,没有通过构造方法构造一个比较器进去
//给构造方法添加一个比较器
TreeSet<WuGui> wuGuis = new TreeSet<>(new WuguiComparator());
wuGuis.add(new WuGui(200));
wuGuis.add(new WuGui(30));
wuGuis.add(new WuGui(50));
wuGuis.add(new WuGui(10));
wuGuis.add(new WuGui(100));
for (WuGui w : wuGuis) {
System.out.println(w);
}
}
}
运行结果:
WuGui{age=10}
WuGui{age=30}
WuGui{age=50}
WuGui{age=100}
WuGui{age=200}
改进上面测试类(使用匿名内部类)代码如下:
public class TreeSetText05 {
public static void main(String[] args) {
//第三种!! //使用匿名内部类的方式 这个类没有名字,直接new接口!!
TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
@Override
public int compare(WuGui o1, WuGui o2) {
return o1.age - o2.age;
}
});
wuGuis.add(new WuGui(200));
wuGuis.add(new WuGui(30));
wuGuis.add(new WuGui(50));
wuGuis.add(new WuGui(10));
wuGuis.add(new WuGui(100));
for (WuGui w : wuGuis) {
System.out.println(w);
}
}
}