集合
集合概念
对象的容器,实现了对对象常用的操作,类似于数组的功能
集合和数组的区别:
数组长度固定,集合长度不固定
数组可以存储基本类型和引用类型,集合只能引用类型
Collection父接口
特点没代表一组任意类型的对象,无序,无下标,不能重复
List接口:有序,有下标。元素可以重复
Set接口:无序,无下标,元素不能重复
package chapter;
import oop.Demo08.Student;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo02 {
public static void main(String[] args) {
//新建collection对象
Collection coll=new ArrayList();
Demo02Test dt1 = new Demo02Test("张三",20);
Demo02Test dt2 = new Demo02Test("张无忌",20);
Demo02Test dt3 = new Demo02Test("网二",20);
//添加数据
coll.add(dt1);
coll.add(dt2);
coll.add(dt3);
System.out.println("元素个数"+coll.size());
System.out.println(coll);
//删除和清空
//coll.clear();
//coll.remove(dt1);
//遍历
for (Object obj:coll){
Demo02Test s=(Demo02Test) obj;
System.out.println(s.toString());
}
//迭代器遍历
Iterator it = coll.iterator();
while (it.hasNext()){
Demo02Test a = (Demo02Test) it.next();
System.out.println(a);
}
//判断
System.out.println(coll.contains(dt1));
}
}
/*
package chapter;
public class Demo02Test {
private String name;
private int age;
public Demo02Test() {
}
public Demo02Test(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 "Demo02Test{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
*/
package chapter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo01 {
public static void main(String[] args) {
//创建集合
Collection coll=new ArrayList();
//添加元素
coll.add("苹果");
coll.add("西瓜");
coll.add("榴莲");
System.out.println(coll.size());
System.out.println(coll);
//删除元素
// coll.remove("榴莲");
// coll.clear();
// System.out.println(coll.size());
//遍历元素
//使用增强for循环
for (Object obj:coll){
System.out.println(obj);
}
//使用迭代器,是一种专门用来遍历集合的一种方式
//hasNext有没有下一个元素,返回值true或者false
//next获取下一个元素
//remove删除当前元素
Iterator it=coll.iterator();
while (it.hasNext()){
String s=(String)it.next();
System.out.println(s);
}
//判断
System.out.println(coll.contains("西瓜"));
System.out.println(coll.isEmpty());
}
}
list子接口
特点:有序,有下标,元素可以重复
package chapter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Demo03 {
public static void main(String[] args) {
//先创建集合对象
List list=new ArrayList();
//添加元素
list.add("苹果");
list.add("小米");
list.add(0,"华为");
//输出一下元素列表
System.out.println("元素数量"+list.size());
System.out.println(list.toString());
//删除元素
// list.remove("华为");
// list.remove(1);
// System.out.println("删除之后"+list.size());
// System.out.println(list.toString());
//遍历操作
//1.使用for遍历,因为list存在角标
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//使用增强for循环
for (Object obj:list){
System.out.println(obj);
}
//使用迭代器
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//使用列表迭代器,和iterator的区别,ListIterator可以向前向后遍历,可以添加删除修改元素
ListIterator lit=list.listIterator();
System.out.println("使用列表迭代器从前往后");
while(lit.hasNext()){
System.out.println(lit.nextIndex()+":"+lit.next());
}
//使用列表迭代器从后往前
while (lit.hasPrevious()){
System.out.println(lit.previousIndex()+":"+lit.previous());
}
//判断
System.out.println(list.contains("苹果"));
System.out.println(list.isEmpty());
//获取位置
System.out.println(list.indexOf("华为"));
}
}
package chapter;
import java.util.ArrayList;
import java.util.List;
public class Demo04 {
public static void main(String[] args) {
List list=new ArrayList();
//添加数字元素
list.add(20);
list.add(30);
list.add(40);
list.add(50);
list.add(60);
System.out.println(list.size());
System.out.println(list);
//删除操作
// list.remove(0);删除第0号元素
//如果想要删除数值,需要先把数值用interger创建出缓存池中的位置
// list.remove(new Integer(20));
//补充方法sublist,返回子集合,含头不含尾
List sub=list.subList(1,3);
System.out.println(sub);
}
}
List实现类
ArrayList是一个重点。数组列表集合
数组结构实现,查询快,增删慢
jdk1.2版本,运行效率快,线程不安全
Vector
数组结构实现,查询快,增删慢
jdk1.0版本,运行效率慢,线程安全!!了解即可
LinkedList
链表结构实现,增删快,查询慢
arraylist代码
package chapter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class Demo05 {
public static void main(String[] args) {
ArrayList arrayList=new ArrayList();
//创建集合,创建元素,添加元素
Demo02Test s1 = new Demo02Test("刘德华", 20);
Demo02Test s2 = new Demo02Test("郭富城", 20);
Demo02Test s3 = new Demo02Test("梁朝伟", 20);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println("元素个数"+arrayList.size());
System.out.println(arrayList);
//删除元素
// arrayList.remove(s1);
// arrayList.remove(new Demo02Test("刘德华", 20));//equal(tgis==obj)进行比较,查看元素是否在堆里面
//去重写equal方法
System.out.println("删除之后,看看元素少了没"+arrayList.size());
//遍历元素
Iterator it=arrayList.iterator();
while (it.hasNext()){
Demo02Test dt2=(Demo02Test) it.next();
System.out.println(dt2);
}
//列表迭代器
ListIterator li=arrayList.listIterator();
while (li.hasNext()){
Demo02Test dt2=(Demo02Test) li.next();
System.out.println(dt2);
}
while (li.hasPrevious()){
Demo02Test dt2=(Demo02Test) li.previous();
System.out.println(dt2);
}
//判断
System.out.println(arrayList.contains(new Demo02Test("刘德华", 20)));
System.out.println(arrayList.isEmpty());
//查找
System.out.println(arrayList.indexOf(s1));
}
}
ArrayList源码分析
默认容量DEFAULT_CAPACITY=10
注意:如果没有向集合中添加任何元素的时候,容量为0,添加任意元素之后,容量变为10,当size超过容量时候,扩容大小为当前的一点五倍,10变为15
elementData用来存放元素的数组
size实际的元素个数
add()方法:添加元素
vector
package chapter;
import java.util.Enumeration;
import java.util.Vector;
public class Demo06 {
public static void main(String[] args) {
//vector集合的使用
Vector vector= new Vector();
vector.add("苹果");
vector.add("香蕉");
vector.add("榴莲");
//遍历:枚举器
Enumeration en=vector.elements();
while (en.hasMoreElements()){
String o=(String) en.nextElement();
System.out.println(o);
}
//判断
System.out.println(vector.contains("西瓜"));
System.out.println(vector.isEmpty());
//其他方法
//firstElement lastElement emementAt
}
}
泛型
好处:提高代码的重用性
防止类型转换异常,提高代码的安全性
Java泛型本质是参数化类型,吧类型作为参数传递
常见形式有泛型类,泛型接口,泛型方法
语法:<T,...>T称为类型占位符,表示一种引用类型
泛型类
package chapter;
public class Demo08<T> {
//泛型类,类名<T>
//T是类型占位符,表示一种引用类型,如果编写多个使用逗号隔开
//创建变量
T t;
//泛型作为方法的参数
public void show(T t){
System.out.println(t);
}
//泛型作为方法的返回值
public T getT(){
return t;
}
}
/*
package chapter;
public class Demo08Test {
public static void main(String[] args) {
//使用泛型类来创建对象
//注意:1.泛型只能使用引用类型
//2.不同泛型对象不能互相复制
Demo08<String> stringDemo08 = new Demo08<String>();
stringDemo08.t="hello";
stringDemo08.show("是我,嘿嘿嘿");
String t = stringDemo08.getT();
Demo08<Integer> inin = new Demo08<>();
inin.t=60;
inin.show(200);
Integer t1 = inin.getT();
}
}
*/
泛型接口
泛型接口有两种实现形式
package chapter;
public interface Demo09<T> {
//泛型接口:语法,接口名<T>
T server(T t);
}
当定义完接口之后有两种方式去实现接口的方法
package chapter;
public class Demo09Test implements Demo09<String>{
@Override
public String server(String s) {
System.out.println(s);
return s;
}
}
/*
Demo09Test d09t = new Demo09Test();
d09t.server("***");
*/
直接在连接接口的时候定义引用类型
package chapter;
public class Demo09Test2<T> implements Demo09<T>{
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
/*
Demo09Test2<Object> objectDemo09Test2 = new Demo09Test2<>();
objectDemo09Test2.server("****");
*/
继续在类中使用泛型类,来实现接口的方法。
泛型方法
只能在方法中使用该泛型
泛型方法调用的时候根据传入的实际参数来使用不同的类型
相当于方法的重载
泛型集合
参数化类型,类型安全的集合,强制集合元素的类型必须一致
特点:编译时即可检查,而非运行时抛出异常
访问时,不比类型转换(拆箱
不同泛型之间引用不能互相赋值,泛型不存在多态
理解:在创建集合的时候使用泛型创建,那么在添加集合元素的时候,只能添加那一类型的元素,好处是不需要强制转换了
package chapter;
import java.util.ArrayList;
public class Demo11 {
public static void main(String[] args) {
ArrayList<String> arr= new ArrayList<String>();//在创建集合项的时候就已经确定了元素类型,
// 所以在添加元素时只能添加该类型元素,好处是遍历的时候不需要强转
arr.add("zhangsan");
arr.add("任笨笨");
arr.add("王新宇");
for (String str: arr
) {
System.out.println(str);
}
}
}
set接口使用
package chapter2;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo01 {
public static void main(String[] args) {
//创建集合
Set<String> set=new HashSet<>();
//添加数据
set.add("苹果");
set.add("华为");
set.add("小米");
System.out.println("数据个数:"+set.size());
System.out.println(set);
//删除数据
// set.remove("苹果");
// set.clear();
// System.out.println("数据个数:"+set.size());
// System.out.println(set);
//遍历
//增强for循环
for (String string:set
) {
System.out.println(string);
}
//迭代器
Iterator<String> it = set.iterator();
while (it.hasNext()){
String next = it.next();
System.out.println(next);
}
}
}
set实现类
HashSet重点
基于hashcode计算元素存放位置
当存入元素的哈希码相同时,会调用equals进行缺,如果结果为true,会拒绝元素进入。
package chapter2;
import java.util.HashSet;
import java.util.Iterator;
//HashSet集合的使用
//存储结构:哈希表(数组列表加红黑树
//无序,不允许出现重复
public class Demo02 {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();//新建集合
hashSet.add("刘德华");//添加元素
hashSet.add("梁朝伟");
hashSet.add("林志玲");
hashSet.add("周润发");
System.out.println("元素个数"+hashSet.size());
System.out.println(hashSet);
//删除数据
// hashSet.remove("刘德华" );
// hashSet.clear();
//遍历
//增强for
for (String str:hashSet
) {
System.out.println(str);
}
//迭代器
Iterator<String> it = hashSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//判断
System.out.println(hashSet.contains("刘德华"));
System.out.println(hashSet.isEmpty());
}
}
hashcode的存储过程:
根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空,执行第二步
在执行equals方法,如果equals方法为true,则认为是重复,否则形成链表
TreeSet
基于排序顺序实现元素不重复
实现类sortedSet接口,对集合元素自动排序
元素对象的类型必须实现Comparable接口,指定排序规则
通过compareTo方法确定是否为重复元素
package chapter2;
import java.util.Iterator;
import java.util.TreeSet;
public class Demo05 {
//使用TreeSet保存数据
//存储结构:红黑树
//要求:元素必须要实现Comparable接口,conpareTi()方法返回值为0时候,认为是重复元素
public static void main(String[] args) {
TreeSet<Person> tree = new TreeSet<>();
Person n1 = new Person("adc", 20);
Person n2 = new Person("xyz", 20);
Person n3 = new Person("zhangsan", 20);
Person n4 = new Person("zhangsan", 23);
tree.add(n1);
tree.add(n2);
tree.add(n3);
tree.add(n4);
System.out.println("元素个数"+tree.size());
System.out.println(tree);
//删除
tree.remove(n1);
//遍历
for (Person per:tree
) {
System.out.println(per);
}
Iterator<Person> it = tree.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//判断
System.out.println(tree.contains(new Person("zhangsan", 23)));
}
}
通过使用comparetor来订制比较
package chapter2;
import java.util.Comparator;
import java.util.TreeSet;
public class Demo06 {
/*
TreeSet集合的使用
Comparetor实现定制比较
*/
public static void main(String[] args) {
//创建集合,并且制定比较规则
TreeSet<Person> person2=new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1=o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
});
Person n1 = new Person("adc", 20);
Person n2 = new Person("xyz", 20);
Person n3 = new Person("zhangsan", 20);
Person n4 = new Person("zhangsan", 23);
person2.add(n1);
person2.add(n2);
person2.add(n3);
person2.add(n4);
System.out.println(person2);
}
}
一个例子,通过使用treeset集合以及CompareTor的订制方法来实现对一组字符串进行长度比较排序
package chapter2;
import java.util.Comparator;
import java.util.TreeSet;
public class Demo07 {
//比较字符串,按照长度进行排序
public static void main(String[] args) {
//创建集合并且制定比较规则
TreeSet<String> terrset=new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1=o1.length()-o2.length();
int n2=o1.compareTo(o2);
return n1==0?n2:n1;
}
});
terrset.add("helloworld");
terrset.add("pingguo");
terrset.add("zhangsan");
terrset.add("lisi");
terrset.add("beijing");
terrset.add("xian");
terrset.add("nanjing");
terrset.add("cat");
System.out.println(terrset);
}
}
Map集合
map接口的特点
- 用于存储任意键值对
- 键:无序,无下标,不允许重复
- 值:无序,无下标,允许重复
package chapter2;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
Map接口的使用
特点:
1.存储键值对2.键不能重复,值可以重复3.无序
*/
public class Demo08 {
public static void main(String[] args) {
//创建集合
HashMap<String, String> map = new HashMap<>();
//添加数据
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美国");
map.put("cn","zhongguo");
System.out.println("元素个数:"+map.size());
System.out.println(map);//由于键值对的存在,所以在添加第四个元素时候,当键相同时候,会修改对应的数据
//删除元素
//map.remove("usa","美国");
//System.out.println("元素个数:"+map.size());
//遍历
//使用keyset方法
Set<String> set = map.keySet();
for (String key:set
) {
System.out.println(key+"..."+map.get(key));
}
//使用entryset方法
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String,String > key:entries
) {
System.out.println(key.getKey()+"..."+ key.getValue());
}
//判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("cn"));
}
}
package chapter2;
import java.util.HashMap;
import java.util.Map;
public class Demo09 {
//hashmap集合的使用
//存储结构:哈希表(数组+链表+红黑树
//使用key以hashcode和equals作为判断重复的依据
public static void main(String[] args) {
HashMap<Student, String> students = new HashMap<>();
Student n1 = new Student("孙悟空", 100);
Student n2 = new Student("猪八戒", 101);
Student n3 = new Student("沙和尚", 102);
students.put(n1,"北京");
students.put(n2,"上海");
students.put(n3,"杭州");
students.put(new Student("沙和尚", 102),"杭州");
System.out.println("个数"+students.size());
System.out.println(students);
//删除
//students.remove(n1);
//遍历
//使用keyset方法
for (Student key: students.keySet()
) {
System.out.println(key.toString()+"..."+students.get(key));
}
//使用entryset方法
for (Map.Entry<Student,String> entry:students.entrySet()
) {
System.out.println(entry.getKey()+"..."+entry.getValue());
}
//判断
System.out.println(students.containsValue("杭州"));
System.out.println(students.containsKey(new Student("沙和尚", 102)));
}
}
map集合的总结:
- hashmap刚刚创建时,table是null。为了节省空间,当添加第一个元素的时,table的容量调整为16
- 当元素个数大于阈值16*0.75=12时候,会进行扩容,扩容之后的大小为原来的两倍,目的是减少调整元素的个数
- jdk1.8:当每一个链表长度大于八并且元素个数大于等于64的时候,会调整为红黑树,目的是提高执行效率
- jdk1.8:当链表长度小于6时候,调整成链表
- jdk1.8以前,链表是头插法,以后是尾插法
Colletions工具类
概念:集合工具类定义了除了存取以外的集合常用方法
package chapter2;
import java.util.*;
public class Demo10 {
public static void main(String[] args) {
//collections工具类的使用
List<Integer> list=new ArrayList<>();
list.add(20);
list.add(32);
list.add(56);
list.add(10);
list.add(2);
//sort排序
System.out.println("排序之前"+list.toString());
Collections.sort(list);
System.out.println("排序之后"+list.toString());
//binarySearch按照下标查找数值(二分查找
int i = Collections.binarySearch(list, 3);
System.out.println(i);
//copy复制
//需要先向新数组中添加数组长度的数字,防止下标越界
List<Integer> dest=new ArrayList<>();
for (int j = 0; j < list.size(); j++) {
dest.add(0);
}
Collections.copy(dest,list);
System.out.println(dest);
//reverse反转
Collections.reverse(list);
System.out.println("反转之后"+list);
//shuffle打乱
Collections.shuffle(list);
System.out.println(list);
//补充,list转化为数组
Integer[] arr = list.toArray(new Integer[5]);
//Integer[] arr = list.toArray(new Integer[10]);
//新数组长度为10 的时候会把多于的位置默认为null
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
//数组转化为集合
String[] names={"zhangsan","lisi","wangwu"};
List<String> list2 = Arrays.asList(names);//集合是一个受限制的集合,不能进行添加和删除
System.out.println(list2);
}
}
集合总结
- 集合的概念:对象的容器,和数组相似,定义了对多个对象进行操作的常用方法
- List集合:有序,有下标,元素可以重复(ArrayList,LinkedList,Vector
- Set集合:无序,无下标,元素不可以重复(HashSet,TreeSaet
- Map集合:存储一对数据,无序,无下标,键不可以重复,值可以重复(HashMap,HashTable,TreeMap
- Collection:集合工具类,定义了除了存取以外的集合常用方法