集合
是一个容器
数组:原生的数组,删除元素不方便,长度是固定的,容量不够时,还需要自己进行扩容,现实中,程序在运行时,数据会时刻变化的,
所以为满足程序运行中各种变化的数据存储需求,java语言中,封装了许多的类,来帮助我们完成不同数据的存储,这些类就被称为集合类。
核心思想我们要学习一些类,这些类对数组进行了封装,让我们更加方便使用
4个接口 7个实现类
单列集合
Collection
List 可以存储重复元素
ArrayList 数据链表
LinkedList链表列表
Vector 线程安全的数组列表
set
HashSet 哈希集合
TreeSet 树形集合
Map 双列集合
键 :值
HashMap 哈希集合
TreeMap 树形集合
java中提供了不同结构的容器类,来存储不同的数据
单列集合
Collection
List
List接口实现类的集合,可以存储重复元素,有序地(按照添加顺序排列),还可以通过索引操作元素
ArrayList 数组列表
由于数组中的每个空间都是连续的,所以查询非常方便可以直接通过下标获取指定位置的元素,但是要删除元素时就比较麻烦删除后其他元素要进行位移
package com.ffyc.javapi.day1; import java.util.ArrayList; public class ArrayListDemo1 { /* ArrayList 数组列表 可以动态增长数组 ArrayList<E> 建议使用泛型的语法,为集合的数据设定数据类型 java中的集合,建议值存储一种类型 底层有一个transien Object[] elementDate;数组 add():默认是向集合的末尾添加元素,首次底层会初始化一个长度为10的数组,当元素添加满了的时候, 会发生扩容操作,扩容为原来的1.5倍 */ public static void main(String[] args) { ArrayList<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.add("f"); alist.add("g"); alist.add("h"); alist.add("i"); alist.add("j"); alist.add(0,"A");//指定位置田家庵 // alist.clear();//清空 alist.remove(1);//删除指定位置的元素 alist.remove("h");//删除指定内容的元素 System.out.println(alist.size());//获取集合中实际有多少个元素 System.out.println(alist.get(4));//查找指定位置元素 System.out.println(alist); } }
package com.ffyc.javapi.day1; import java.util.ArrayList; import java.util.Arrays; public class ArrayListDemo2 { public static void main(String[] args) { ArrayList<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.add("f"); alist.add("g"); alist.add("h"); alist.add("i"); alist.add("j"); System.out.println(alist.contains("d"));//是否包含某个属性 System.out.println(alist.isEmpty());//判断集合是否为空 alist.ensureCapacity(20);//扩容底层数组为20 System.out.println(alist.indexOf("c"));//查找某个元素在数组中首次出现的位置,前到后 System.out.println(alist.lastIndexOf("c"));//查找某个元素在数组中首次出现的位置,后到前 alist.set(0,"A");//代替 Object[] objs = alist.toArray();//将集合转为Object类型 String [] arrays = alist.toArray(alist.toArray(new String[alist.size()]));//将集合转为指定类型 System.out.println(Arrays.toString(arrays)); System.out.println(alist); } }
LikedList 链表列表
每一个数据存储在一个Node类中 Node节点
Node
prev
data
next
链表结构,对外只提供头,尾节点,没词查询元素时,非常慢,必须从头或者从尾开始,如果从中间删除某个元素时非常快,只需要改变next节点的内存地址即可,元素不需要移动位置
查询慢,但是中间增加删除快 方法和ArrayList基本相同
package com.ffyc.javapi.day1; import java.util.LinkedList; public class LinkedListDemo1 { /* LinkedList add();向链表中添加元素,不存在扩容问题。 */ public static void main(String[] args) { LinkedList<String> llist = new LinkedList<>(); llist.add("a"); llist.add("b"); llist.add("c"); llist.add("d"); llist.add("e"); llist.add("f"); llist.add("g"); llist.add("h"); llist.add("i"); llist.add("j"); llist.add("k"); llist.addFirst("S");//向头节点添加元素 llist.add(1,"A"); System.out.println(llist.getFirst());//获得第一个元素 System.out.println(llist.removeFirst());//删除并返回第一个元素 System.out.println(llist.get(3)); } }
Vector数组列表(线程安全的)
package com.ffyc.javapi.day1; import java.util.Vector; public class VectorDemo { /* Vector 数组链表 里面的方法都添加了synchronized关键字,是线程安全的 */ public static void main(String[] args) { Vector<Integer> v = new Vector<>(); v.add(1); v.add(2); v.add(3); v.add(4); v.add(5); v.add(6); v.add(7); v.add(7); v.add(9); v.add(10); System.out.println(v); } }
集合遍历
package com.ffyc.javapi.day1; import java.util.ArrayList; public class ListFor { public static void main(String[] args) { ArrayList<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.add("f"); alist.add("g"); alist.add("h"); alist.add("i"); alist.add("j"); /* for循环进行遍历 在遍历时,是可以删除元素的,删除时需要注意元素的移动,以及索引的变化 */ for(int i = 0;i< alist.size();i++){ String item = alist.get(i); System.out.println(item); } /* 增强for循环 在遍历元素是不允许从集合中删除元素,如果从集合中删除元素就会报ConcurrentModificationException */ // for(String item : alist){ // if(item.equals("c")){ // alist.remove(item); // } // System.out.println(item); // } } }
Iterator关键字
package com.ffyc.javapi.day2; import java.util.ArrayList; import java.util.Iterator; public class ListFor2 { public static void main(String[] args) { ArrayList<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.add("f"); alist.add("g"); alist.add("h"); alist.add("i"); alist.add("j"); /* java中提供了对于集合进行遍历的迭代器 里面维护了一个指针(计数器),当删除元素时,计数器会自动回退 */ Iterator<String> it = alist.iterator(); while (it.hasNext()){//判断有没有下一个元素 String item = it.next();//取出元素 if(item.equals("c")){ it.remove();//使用迭代器方法进行删除元素 } } System.out.println(alist); } }
ListIterator关键字
package com.ffyc.javapi.day2; import java.util.ArrayList; import java.util.ListIterator; public class ListFor3 { public static void main(String[] args) { ArrayList<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.add("f"); alist.add("g"); alist.add("h"); alist.add("i"); alist.add("j"); ListIterator<String> lit = alist.listIterator(); while (lit.hasNext()){ String item = lit.next(); System.out.println(item); } //从后向前遍历取前一个元素 ListIterator<String> li = alist.listIterator(alist.size()); while (li.hasPrevious()){ String item = li.previous(); System.out.println(item); } } }
Set
Set接口实现类的集合,不可以存储重复元素,添加时,会自定的判断,有的是无序的,有的是有序的,
HashSet:
HashSet:是无序的,即不按照添加的顺序业不按照自然顺序存放
是调用hsahCode()方法进行计算hash值,为了更快速判段
但是hash判断是不安全·的
当hash值相同时再调用equals方法判断内容是否相同,保证了安全
package com.ffyc.javapi.day2; import java.util.HashSet; public class HashSetDemo1 { public static void main(String[] args) { /* HashSet不能存储重复元素,且存储的元素是无序的 添加元素时是如何去除重复元素的 判断元素是否重复时没有直接使用equals()方法进行判断,因为效率低 java中在比较是否重复时,先是调用hashCode(),计算出内容的hash值(整数) 两个整数判断是否相等,是比较简单并且快,但是不同内容计算出来的hash值有可能相同 当hash值出现相同时再调用equals()方法进行判断, 、这样即安全又快。 存储自定义对象时,类中默认没写hashCode();equals都调用的是Object类中 Object中hashCode方法,默认获取的对象是内存地址 */ HashSet<String> haset = new HashSet<>(); haset.add("b"); haset.add("c"); haset.add("r"); haset.add("a"); haset.add("通话"); haset.add("种地"); haset.add("e"); haset.add("a"); System.out.println(haset.contains("a")); // haset.clear(); System.out.println(haset.isEmpty()); System.out.println(haset.size()); System.out.println(haset); } }
重写HashCoad方法 package com.ffyc.javapi.day2; import java.util.Objects; public class HashSetDemo2 { private int num; private String name; public HashSetDemo2(int num, String name) { super(); this.num = num; this.name = name; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Car{" + "num=" + num + ", name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; HashSetDemo2 that = (HashSetDemo2) o; if (num != that.num) return false; return name != null ? name.equals(that.name) : that.name == null; } @Override public int hashCode() { int result = num; result = 31 * result + (name != null ? name.hashCode() : 0); return result; } } 测试方法 package com.ffyc.javapi.day2; import java.util.HashSet; public class HashSetDemo3 { public static void main(String[] args) { HashSetDemo2 car1 = new HashSetDemo2(101,"宝马1"); HashSetDemo2 car2 = new HashSetDemo2(102,"宝马2"); HashSetDemo2 car3 = new HashSetDemo2(103,"宝马3"); HashSetDemo2 car4 = new HashSetDemo2(101,"宝马1"); HashSetDemo2 car5 = new HashSetDemo2(104,"宝马5"); HashSet<HashSetDemo2> hset = new HashSet<>(); hset.add(car1); hset.add(car2); hset.add(car3); hset.add(car4); hset.add(car5); System.out.println(hset); } }
TreeSet
TreeSet:是有序地(按照自然顺序存放)
set中添加的类中必须要实现Comparable接口,支持比较大小进行排序
package com.ffyc.javapi.day2; import java.util.TreeSet; public class TreeSetDemo1 { public static void main(String[] args) { /* 不能存储重复元素 可以按照自然顺序排序 */ TreeSet<String> tset = new TreeSet<>(); tset.add("c"); tset.add("b"); tset.add("a"); tset.add("d"); tset.add("c"); System.out.println(tset); } }
package com.ffyc.javapi.day2; import java.util.TreeSet; public class TreeSetDemo2 { public static void main(String[] args) { /* 不能存储重复元素 可以按照自然顺序排序 向treeSet中添加元素的类,必须要实现Comparable接口,支持比较大小进行排序 */ Car car1 = new Car(101,"宝马1"); Car car2 = new Car(102,"宝马2"); Car car3 = new Car(103,"宝马3"); Car car4 = new Car(101,"宝马1"); Car car5 = new Car(104,"宝马5"); TreeSet<Car> tset = new TreeSet<>(); tset.add(car1); tset.add(car2); tset.add(car3); tset.add(car4); tset.add(car5); System.out.println(tset); } } 写car类 package com.ffyc.javapi.day2; public class Car implements Comparable<Car>{ private int num; private String name; public Car(int num, String name) { super(); this.num = num; this.name = name; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Car{" + "num=" + num + ", name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Car car = (Car) o; if (num != car.num) return false; return name != null ? name.equals(car.name) : car.name == null; } @Override public int hashCode() { int result = num; result = 31 * result + (name != null ? name.hashCode() : 0); return result; } @Override public int compareTo(Car o) { return this.num-o.num; } }
遍历方式
set集合不支持索引操作,不能用普通for循环
增强for循环
迭代器遍历 只支持Iterator关键字进行遍历
package com.ffyc.javapi.day2; import java.util.ArrayList; import java.util.Iterator; public class ListFor2 { public static void main(String[] args) { ArrayList<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.add("f"); alist.add("g"); alist.add("h"); alist.add("i"); alist.add("j"); System.out.println(alist); /* java中提供了对于集合进行遍历的迭代器 里面维护了一个指针(计数器),当删除元素时,计数器会自动回退 */ Iterator<String> it = alist.iterator(); while (it.hasNext()){//判断有没有下一个元素 String item = it.next();//取出元素 if(item.equals("c")){ it.remove();//使用迭代器方法进行删除元素 } } System.out.println(alist); } }
package com.ffyc.javapi.day2; import java.util.ArrayList; import java.util.ListIterator; public class ListFor3 { public static void main(String[] args) { ArrayList<String> alist = new ArrayList<String>(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.add("f"); alist.add("g"); alist.add("h"); alist.add("i"); alist.add("j"); ListIterator<String> lit = alist.listIterator(); while (lit.hasNext()){ String item = lit.next(); System.out.println(item); } //从后向前遍历取前一个元素 ListIterator<String> li = alist.listIterator(alist.size()); while (li.hasPrevious()){ String item = li.previous(); System.out.println(item); } } }
Map
双列数据存储
键-->值
键值映射
键不能重复 值可以重复
每个键最多只能映射到一个值
HashMap
package com.ffyc.javapi.day2; import java.util.Collection; import java.util.HashMap; import java.util.Set; public class HashMapDemo { public static void main(String[] args) { /* Map 键值对形式进行存储 键不可重复,值可以重复 HashMap 键是无序的,只能存储一个为null的值 */ HashMap<String,String> map = new HashMap<>(); map.put("a","aa"); map.put("z","zz"); map.put("s","ss"); map.put("h","hh"); map.put("a","aaa"); // map.clear();//清空所有键值对 // map.remove("a");//删除指定的key System.out.println(map.get("h"));//获取值 System.out.println(map.containsKey("h"));//判断是否包含指定的key System.out.println(map.containsValue("hh"));//包含值 System.out.println(map.isEmpty()); System.out.println(map.size()); // Collection<String> list= map.values(); // System.out.println(list); Set<String> keyset= map.keySet();//获取map中所有的key for(String key :keyset){ String v = map.get(key); System.out.println(key+"::"+v); }//通过key进行遍历 System.out.println(map); } }
HashMap遍历
package com.ffyc.javapi.day3; import java.util.HashMap; import java.util.Map; import java.util.Set; public class HashMapDemo3 { public static void main(String[] args) { HashMap<String,String> map = new HashMap<>(); map.put("a","aa"); map.put("z","zz"); map.put("s","ss"); map.put("h","hh"); map.put("a","aaa"); /* 方式一:通关keySet();获取map中所有的key的集合 变相的遍历map Set<String> keySet = map.keySet(); for(String key : keySet){ System.out.println(map.get(key)); } 方式二:在遍历时,将key-value元素,封装到一个Entry对象中,Entry对象中包含了key和Value */ Set<Map.Entry<String,String>> entrySet = map.entrySet(); for(Map.Entry<String,String> entry : entrySet){ System.out.println(entry.getKey()+":"+entry.getValue()); } } }
TreeMap
package com.ffyc.javapi.day3; import java.util.TreeMap; public class TreeMapDemo { public static void main(String[] args) { /* 是一个键值对的存储 可以根据键进行排序 键的类型要实现Comparable接口,来进行排序 */ TreeMap<String,Integer> tmap = new TreeMap<>(); tmap.put("c",2); tmap.put("b",3); tmap.put("a",1); tmap.put("d",4); tmap.put("c",33); System.out.println(tmap); } }
Hashtable
package com.ffyc.javapi.day3; import java.util.Hashtable; public class HashtableDemo1 { public static void main(String[] args) { /* 键值对存储 Hashtable底层结构与HashMap类似,但是Hashtable是线程安全的 Hashtable中不能存储为null的key */ Hashtable<String,String> ht = new Hashtable<>(); ht.put("a","a"); ht.put("s","s"); ht.put("w","w"); ht.put("g","g"); ht.put("a","a"); System.out.println(ht); } }
Collections
提供了关于集合操作的方法类似于Arrays类
常用方法实现
package com.ffyc.javapi.day3; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class CollectionsDemo1 { public static void main(String[] args) { /* addAl l(Collection<? super T> c, T... elements); binarySearch(List<? extends Comparable<? super T>> l ist, T key) sort(List<T> l ist) sort(List<T> l ist, Comparator<? super T> c) swap(List<?> l ist, int i, int j) copy(List<? super T> dest, List<? extends T> src) ; 注意 dest size需大于等于src.size emptyList() 返回为空的集合,不能添加数据 fi l l(List<? super T> l ist, T obj) max(Col lection<? extends T> col l)//返回最大最小值 min(Col lection<? extends T> col l) replaceAl l(List<T> l ist, T oldVal, T newVal) reverse(List<?> l ist) shuffle(List<?> l ist) 随机排序 copy(dest,src)集合复制 */ // CollectionsDemo1.test(1,2,3); ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("c"); list.add("b"); list.add("d"); // Collections.addAll(list,"c","b","d");//加入数组 System.out.println(Collections.binarySearch(list,"b"));//二分查找 Collections.sort(list);//排序 Collections.swap(list,0,3);//交换指定位置元素 ArrayList<String> dest = new ArrayList<>(); dest.add("1"); dest.add("2"); dest.add("3"); dest.add("4"); dest.add("5"); Collections.copy(dest,list);//把原数组复制到目标数组里面去,目标数组的size()大于等于原数组的size(); System.out.println(list); Collections.reverse(list);//逆序 Collections.shuffle(list);//随机排序 System.out.println(dest); // List emptyList = Collections.emptyList();//返回一个空集合,这个空集合是一个内部类,不能使用,为了避免出现空指针 // Collections.fill(list,"+");//用指定的内容填充集合 System.out.println(list); } /* int...a可变长度参数本质是一个数组 在一个参数链表中,只能有一个可变长度的参数,并且只能放在参数链表的最后一位 */ public static void test(int b, int...a){ System.out.println(Arrays.toString(a)); } }