1.Collection接口
1.1介绍
英文名称Collection,是用来存放对象的数据结构。其中长度可变,而且集合中可以存放不同类型的对象。并提供了一组操作成批对象的方法。
数组的缺点:长度是固定不可变的,访问方式单一,插入、删除等操作繁琐。
1.2 集合的继承结构
1.3 常用方法测试
package cn.tedu.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
//这个类用来测试Collection接口
public class Test1_Collection {
public static void main(String[] args) {
//1,创建Collection接口对象
// Collection c = new Collection();//报错,因为Collection是接口不能new
//a,<Integer>是泛型,用来约束集合中元素的类型,只能写引用类型不能是基本类型
Collection<Integer> c = new ArrayList();
//2,常用方法
c.add(100);//添加元素
c.add(200);
c.add(300);
System.out.println(c);
// c.clear();//清空集合
System.out.println( c.contains(300) );//判断集合是否包含指定元素
System.out.println( c.equals(100) );//判断和100是否相等
System.out.println( c.hashCode() );//返回集合的哈希码值
System.out.println( c.isEmpty() );//判断集合是否为空
System.out.println( c.remove(200) );//判断是否成功删除集合中的元素
System.out.println( c.size() );//获取集合的长度/个数
Object[] os = c.toArray();//把集合的元素放入数组
System.out.println( Arrays.toString(os) );
//集合间的操作
Collection<Integer> c2 = new ArrayList();
c2.add(9);
c2.add(8);
c2.add(7);
c.addAll(c2);//把c2加到c里
System.outprintln( c.containsAll(c2) );//判断c中是否包含c2
System.out.println( c.removeAll(c2) );//删除c2
// System.out.println( c.retainAll(c2) );//删除c
System.out.println(c);
//用来 遍历/迭代 集合中的元素Iterator<E> iterator()
Iterator<Integer> it = c.iterator();
//通过Iterator迭代器,循环着获取集合中的元素
while(it.hasNext()) {
//hasNext()用来判断集合中是否有下个元素,有就返回true
Integer inte = it.next();//next()获取迭代到的元素
System.out.println(inte);
}
}
}
2.List接口
2.1介绍
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
2.2常用方法测试
package cn.tedu.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
//这个类用测试List接口
public class Test2_List {
public static void main(String[] args) {
//1,创建List接口对象
List<String> list = new ArrayList();
//2,继承自Collection接口的方法
list.add("jack");//添加元素
list.add("tony");
list.add("hanmeimei");
list.add("tony");
list.add("tony");
list.add("tony");
list.clear();//清空集合
System.out.println( list.contains("jack") );
System.out.println( list.equals("jack") );
System.out.println( list.hashCode() );
System.out.println( list.isEmpty() );
System.out.println( list.remove("hanmeimei") );
System.out.println( list.size() );
System.out.println( list.toArray() );//变成数组
//3,List接口的特有方法 -- 都是可以按照索引来操作的方式
list.add(1, "蔡徐坤");//在指定索引处添加指定的元素
System.out.println(list+"===");
System.out.println(list.get(2));//获取下标对应的元素
System.out.println(list.indexOf("tony"));//获取指定元素第一次出现的下标
System.out.println(list.lastIndexOf("tony"));//获取指定元素最后一次出现的下标
System.out.println(list.remove(3));//按照下标删除指定元素
System.out.println(list.set(0,"xiongda"));//置换元素
List<String> subList = list.subList(2, 4);//截取下标2-4的元素(含头不含尾)
System.out.println(subList);
//TODO 集合间的操作
List<String> list2 = new ArrayList();
list2.add("1");
list2.add("2");
list2.add("3");
System.out.println( list.addAll(list2));//把list2加到list里
System.out.println( list.addAll(1, list2));//在指定下标处添加元素
System.out.println( list.contains(list2));//判断是否包含
System.out.println( list.removeAll(list2));//删除list2
System.out.println( list.retainAll(list2));//删除list
//TODO 集合的迭代 -- List集合的迭代方式有多种:
//iterator() listIterator() for() foreach
//方式1:由于List集合有下标,所以可以根据下标遍历数据
//i < list.size() 下标最大值是集合长度-1
for(int i = 0 ; i < list.size() ; i++) {
String s = list.get(i);//list.get(i)根据下标获取元素
System.out.println(s);
}
//方式2:普通for循环遍历的效率低,可以用foreach提高,好处:语法简洁效率高 坏处:不能按照下标获取
//for(1 2:3){} -- 3是要遍历的数据 1是遍历得到的数据的类型 2是变量名
for(String str:list) {
System.out.println(str);//str代表的是当前遍历到的数据
}
//方式3:iterator() 是继承自父接口Collection的
Iterator<String> it = list.iterator();
while(it.hasNext()) {//hasNext()判读是否有下一个元素
String str = it.next();//next()获取元素
System.out.println(str);//打印获取到的值
}
//方式4:listIterator() 是List接口的特有方法
//Iterator<E> iterator() --父接口 --hasNext() --next() --remove()
//ListIterator<E> listIterator() --子接口,拥有父接口的方法,也有自己的特有方法(逆向迭代)
//public interface ListIterator<E> extends Iterator<E>
ListIterator<String> it2 = list.listIterator();
while(it2.hasNext()) {//hasNext()判断后面有没有数据
String s = it2.next();//next()获取后一个数据
System.out.println(s);//打印获取到的数据
}
//总结:方式3和方式4有什么区别?-- 3是父接口Iterator4是子接口ListIterator
//子接口拥有父接口的所有方法也有自己的特有方法,子接口的特有方法就是向前/逆向遍历
}
}
3.ArrayList实现类
3.1介绍
1.存在于java.util包中。
2.内部用数组存放数据,封装了数组的操作,每个对象都有下标。
3.内部数组默认初始容量是10,如果不够会以1.5倍容量增长。
4.查询快,增删数据效率会降低。
ArrayList的用法和List一样只是创建对象时用的是:
ArrayList<Integer> list = new ArrayList<>();
4.LinkedList实现类
4.1介绍
双向链表,两端效率高,下标遍历效率低,迭代器遍历效率高。底层就是数组和链表实现的。
4.2常用方法测试
package cn.tedu.collection;
import java.util.LinkedList;
//这个类用来测试LinkedList
public class Test4_LinkedList {
public static void main(String[] args) {
//1,创建对象
LinkedList<String> list = new LinkedList();
//2,常用方法
list.add("杰克");
list.add("肉丝");
list.add("凹凸曼");
list.add("蜘蛛侠");
System.out.println(list);
//3,LinkedList特有方法
list.addFirst("美队");//添加首元素
list.addLast("钢铁侠");//添加尾元素
System.out.println(list);
System.out.println( list.getFirst());//获取首元素
System.out.println( list.getLast());//获取尾元素
System.out.println( list.removeFirst());//删除首元素
System.out.println( list.removeLast());//删除尾元素
}
}
5.Set接口
5.1介绍
一个不包含重复元素的 collection。数据无序(因为set集合没有下标)。由于集合中的元素不可以重复。常用于给数据去重。HashSet:底层是哈希表。TreeSet:底层是TreeMap,也是红黑树的形式,便于查找数据。
5.2常用方法测试
package cn.tedu.collection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
//这个类用来测试Set接口的用法
public class Test5_Set {
public static void main(String[] args) {
//1,创建Set对象
// Set set = new Set();//报错,因为Set是接口,不能new
Set<String> set = new HashSet();
//2,常用方法
set.add("jack");
set.add("rose");
set.add("tony");
set.add("hanmeimei");
set.add("tony");
set.add("null");
System.out.println(set);
set.clear();//清空集合
System.out.println(set.contains("tony"));//判断set中是否包含元素
System.out.println(set.equals("tony"));//判断set是否和tony相等
System.out.println(set.hashCode());//获取set集合的哈希码值
System.out.println(set.isEmpty());//判断set集合是否为空
System.out.println(set.remove("null"));//删除集合的指定元素
System.out.println(set.size());//获取集合的长度
Object[] obs = set.toArray();//把集合的元素放入数组中
System.out.println(Arrays.toString(obs));//查看数组里的元素值
//集合间的操作
Set<String> set2 = new HashSet();
set2.add("1");
set2.add("2");
set2.add("3");
System.out.println(set.addAll(set2));//把set2加入到set中
System.out.println(set.containsAll(set2));//判断set中是否包含set2
System.out.println(set.removeAll(set2));//删除set2
System.out.println(set.retainAll(set2));//删除set
//集合的迭代Iterator<E> iterator()
Iterator<String> it = set.iterator();
while(it.hasNext()) {//判断有没有下一个元素
String s = it.next();//获取元素
System.out.println(s);//打印获取到的元素
}
}
}
6.HashSet实现类
6.1介绍
底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。其中,K不许重复。此类允许使用 null 元素。
HashSet的方法用法和Set一样只是创建对象时用的是:
HashSet<Integer> set = new HashSet();
7.Set给自定义对象去重
Set集合去重原理:Set集合去重主要是调用 add 方法时,使用了 hashCode 方法和equals 方法,如果在 Set集合 中找不到与该元素 hashCode 值相同的元素,则说明该元素是新元素,会被添加到 Set 集合中;如果两个元素的 hashCode 值相同,并且使用 equals 方法比较后,返回值为 true,那么就说明两个元素相同,新元素不会被添加到 Set 集合中;如果 hashCode 值相同,但是 equals 方法比较后,返回值为 false ,则两个元素不相同,新元素会被添加到 Set 集合中。
创建学生类
package cn.tedu.collection;
//这个类用来测试set给自定义对象去重
public class Student {
//提供构造方法
public Student() {}
public Student(String name, int age, String addr) {
super();
this.name = name;
this.age = age;
this.addr = addr;
}
//提供私有属性
private String name;
private int age;
private String addr;
//提供set()/get()方法
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 String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
//重写toString()
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", addr=" + addr + "]";
}
//重写hashCode():想要根据两个对象的属性值计算哈希值,
//如果属性值完全都一样,就保证产生的hash值也一样
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((addr == null) ? 0 : addr.hashCode());
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重写equals():要比较对象间的属性值,如果属性值都一样,返回true
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (addr == null) {
if (other.addr != null)
return false;
} else if (!addr.equals(other.addr))
return false;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
测试
package cn.tedu.collection;
import java.util.HashSet;
import java.util.Set;
//这个类用来给自定义对象去重
//总结:
//1、如果你想用Set集合,给自定义对象去重,要求你在自己的类中,同时提供重写的hashCode()和equals()
//--源码摘抄:if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))
//重写的hashCode():我们不适用默认的自动计算出来的哈希值,而是要根据对象的属性值计算,如果对象的属性值都相同,那么请产生相同的哈希值
//重写的equals():我们要比较的不是对象的地址值,而是比较,两个对象间如果属性值都一样就返回true
public class Test7_HashSet2 {
public static void main(String[] args) {
//1,创建Set集合对象
Set<Student> set = new HashSet<Student>();
//2,向set集合中添加自定义对象
Student s1 = new Student("tony",20,"BJ");
Student s2 = new Student("jack",10,"SH");
Student s3 = new Student("rose",30,"SH");
Student s4 = new Student("jack",10,"SH");
Student s5 = new Student("rose",30,"SH");
set.add(s1);
set.add(s2);
set.add(s3);
//重复的添加了属性相同的对象,为什么没有去重??
//1,保证对象拥有相同的哈希值??默认使用的是Object提供的hashCode()计算的哈希值
//如果你想要根据两个对象的属性值计算哈希值,那就需要重写hashCode()
//2,是要保证两个对象间的equals()返回true,那就需要重写equals()
set.add(s4);
set.add(s5);
System.out.println(set);
}
}
网友评论