集合
一,Java集合框架概述
1.什么是集合以及集合包含什么
集合可以作为一种容器,用来储存对象信息.所有集合类都位于java.util
包下,但支持多线程的集合位于java.util.concurrent
包中.
2.集合和数组的区别
集合是用来存储数据的容器,那么我们就会想到之前提到过的数组,同样是用来存储数据的,他们之间有区别吗?
二.Collection接口
Collection 接口-定义了存取一组对象的方法,其子接口Set和List分别定义了存储方式。
- List 中的数据对象有顺序且可以重复。
- Set 中的数据对象没有顺序且不可以重复。
Collection中定义的方法
方法应用
package collectionapi;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo {
public static void main(String[] args) {
Collection c=new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("aba");
Collection b=new ArrayList();
b.add("a");
b.add("b");
System.out.println(c);
//System.out.println(c.contains("a"));//是否包含这个元素
//System.out.println(c.isEmpty());//是否为空
//c.addAll(c);
// System.out.println(c.remove("a"));//移除某个元素
System.out.println(c.containsAll(b));//判断b中元素是否完全包含于c 包含返回true
}
}
1.List接口及实现类
List接口中ArrayList
;LinkedList
;Vector
1)ArrayList
底层数组实现,查询快,增删慢(数组实现,按地址索引查询很快,增删的话需要逐一更改地址)创建之初,在底层常见一个默认长度的数组,当数组满了之后,再想添加时,会扩容一个新数组,为原来额1.5倍
缺点:扩容之后,元素不能存满,浪费空间
package collectionapi;
import java.util.ArrayList;
/*
ArrayList
底层数组实现,查询快,增,删慢
创建之初,在底层创建一个默认长度的数组,当数组内容满了之后,再
在继续添加时,会扩容一个新数组,为原来的1.5倍
缺点:扩容后,元素不能存满,浪费空间
*/
public class ArrayListDemo {
public static void main(String[] args) {
/*
1.调用默认无参的构造方法,创建ArrayList对象时,并没有实际的创建数组,第一次添加
元素时创建数组,默认长度为10
2.调用有参的构造方法,创建ArrayList对象时,创建一个指定长度数组
this.elementData=new Object[initialCapacity]
*/
//ArrayList<String> arrayList1=new ArrayList<String>(5);
ArrayList<String> arrayList=new ArrayList<String>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
arrayList.add("e");
arrayList.add("e");//当add添加元素时,数组已满,会进行扩容,扩展为原来1.5倍,返回一个新数组
arrayList.add(3,"Q");//指定位置进行添加
//System.out.println(arrayList.remove(3));//删除并返回指定位置元素'
//System.out.println(arrayList.indexOf("c"));//查询元素位置
//System.out.println(arrayList.lastIndexOf("e"));//查询元素最后出现位置
System.out.println(arrayList.remove(3));
System.out.println(arrayList.set(3,"d"));//改变指定位置的元素
}
}
package collectionapi;
import java.util.ArrayList;
import java.util.Comparator;
public class ArrayListDemo2 {
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<String>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
//排序
arrayList.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return 0;
}
});
System.out.println(arrayList);
}
}
package collectionapi;
import java.util.ArrayList;
public class MyArray extends ArrayList {
public static void main(String[] args) {
MyArray myArray=new MyArray();
myArray.add("a");
myArray.add("b");
myArray.add("c");
myArray.add("d");
myArray.add("e");
myArray.removeRange(2,4);//删除指定区间元素
}
}
package collectionapi;
import java.util.ArrayList;
public class ArrayListDemo3 {
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<String>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
arrayList.add("e");
ArrayList<String> arrayList1=new ArrayList<String>();
arrayList1.add("a");
arrayList1.add("b");
arrayList1.add("c");
arrayList1.add("d");
arrayList1.add("f");
//arrayList.addAll(arrayList1);//把数组a1加到a上
//System.out.println(arrayList.containsAll(arrayList1));//此集合是否包含指定集合中的元素,包含返回true
//System.out.println(arrayList.removeAll(arrayList1));//删除两个集合中相同的元素,有返回true
System.out.println(arrayList.retainAll(arrayList1));//保留两个集合相同元素,有返回true
System.out.println(arrayList);
}
}
2)LinkedList
采用了链表的存储方式,插入,删除元素快,查找慢
package collectionapi.list;
import java.util.LinkedList;
/*
LinkedList
底层为链表实现,查询慢,增,删快
元素查找从第一个节点向后查找
增加,删除元素时,其他元素位置不动,只需改变指针域的值即可
*/
public class LinkedListDemo {
//LinkedList<String> llist=new LinkedList<>();
LinkedList<String> llist;
public static void main(String[] args) {
LinkedList<String> llist = new LinkedList<>();
//LinkedList里面还提供了许多关于链表头尾操作的方法,这些方法用于模拟队列结构,栈结构操作.
llist.addLast("a");
llist.addLast("b");
llist.addLast("c");
llist.addLast("d");
llist.addLast("e");
llist.clear();//清除
System.out.println(llist.pollFirst());//检索并删除此列表的第一个元素,如果此列表为空,则返回 null 。
System.out.println(llist.peekFirst());//检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。
System.out.println(llist.getFirst());//返回此列表中的第一个元素
System.out.println(llist.removeFirst());//从此列表中删除并返回第一个元素
System.out.println(llist);
llist.addFirst("1");
llist.offerFirst("1");//在此列表的前面插入指定的元素
llist.offerLast("w");//在该列表的末尾插入指定的元素。
}
}
3)Vector
底层是数组实现,线程安全
package collectionapi.list;
import java.util.Vector;
/*
线程安全 数组实现
new Vector<>(); 在创建之初 已经创建底层数组存储 默认长度为10
*/
public class VectorDemo {
public static void main(String[] args) {
Vector<String> vector =new Vector<>();
vector.add("a");
vector.add("c");
vector.add("b");
}
}
4)集合的迭代
集合的迭代 分别是:for
循环遍历;增强for
循环的遍历;以及迭代器遍历(iterator)
package collectionapi.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class IterationDemo {
public static void main(String[] args) {
//test1();
//test2();
//test3();
test4();
}
public static void test1(){
//for循环 可以删除集合中的元素,但是注意 下标与集合中的内容就会不对应
List<Integer> a=new ArrayList<>();
a.add(1);
a.add(2);
a.add(1);
a.add(1);
a.add(3);
a.add(4);
for (int i = 0; i <a.size() ; i++) {
Integer A=a.get(i);
//System.out.println(A);
if(A.equals(1)){
a.remove(A);
}
}
System.out.println(a);
}
public static void test2(){
//foreach 理论上遍历元素时,不允许删除集合中数据
//如果删除,只能删除一次 然后立刻跳出循环
List<Integer> b=new ArrayList<>();
b.add(1);
b.add(2);
b.add(1);
b.add(1);
b.add(3);
b.add(4);
for (Integer B:b) {
if (B.equals(1)){
b.remove(B);
/*
ConcurrentModificationException 同时修改异常
*/
break;
}
}
System.out.println(b);
}
public static void test3(){
/*
迭代遍历器1 iterator
hasNext()判断集合中还有没有元素
remove();删除元素,删除后里面的游标(指针,计数器)会回退一下
*/
List<Integer> c=new ArrayList<>();
c.add(1);
c.add(2);
c.add(1);
c.add(1);
c.add(3);
c.add(4);
Iterator<Integer> iter=c.iterator();
while (iter.hasNext()){
Integer i= iter.next();
if (i.equals(1)){
iter.remove();//使用迭代器中的remove();
}
}
System.out.println(c);
}
public static void test4(){
List<Integer> c=new ArrayList<>();
c.add(1);
c.add(2);
c.add(1);
c.add(1);
c.add(3);
c.add(4);
/*
迭代器2
*/
ListIterator<Integer> listit=c.listIterator();
//listit.nextIndex();//返回对 next 的后续调用所返回元素的索引。
//listit.add(6);
//listit.set(5);
//listit.next();//返回列表的下一个元素
System.out.println(listit.hasPrevious());
while (listit.hasPrevious()){
System.out.println(listit.previous());
}
System.out.println(c);
}
}
三.Set接口
Set接口继承了Collection
接口,Set中储存的元素是不重复的,且无序,没有索引 Set接口的实现类有两个HashSet
和TreeSet
1.HashSet
Hashset
类中元素不能重复,(彼此之间调用equals
方法比较,都返回false)
底层数据结构是哈希表+链表(hash表依赖于hash值储存)
package collectionapi.set;
import java.util.HashSet;
/*
set 不能存储重复元素
HashSet 无序存储(不按添加顺序排列)
*/
public class HashSetDemo {
public static void main(String[] args) {
HashSet<String> h=new HashSet<>();
h.add("a");
h.add("a");
h.add("b");
h.add("c");
h.add("w");
h.add("g");
h.add("t");
h.add("重地");
h.add("通话");
h.add("b");
System.out.println(h);
/*
1.哈希结构的底层是如何存储数据
哈希表:哈希表本质也是数组
2.HashSet是如何去除重复元素的
先用元素的哈希值比较(快) 但是内容不同,hash值可能相同
hash值相同时,再用equals()方法判断内容是否相等 (线程可靠,但是效率低)
双保险:既保证效率有保证安全
*/
}
}
package collectionapi.set;
import java.util.HashSet;
public class HashSetDemo2 {
public static void main(String[] args) {
/*
set 不能存储重复元素
HashSet 无序存储(不按添加顺序排列)
HashSet如何判断元素重复
1.每次添加内容时,会用内容的hash值来判断是否相同,但是hash值这种方法并不安全,
可能出现内容不同,hash值相同(这种方法速度快)
2.当出现内容不同,hash值相同时(hash碰撞 hash冲突),使用equals方法进行比较,比较内容是否
相同(安全)
hash值怎么来
调用HashCode()方法
两种情况:1.类中已经重写HashCode()方法,例如String类 根据内容来计算hash值
2.类中没有重写HashCode()方法,调用object类中打的HashCode()
*/
HashSet<Student> h=new HashSet<>();
Student s=new Student(100,"asd");
Student s2=new Student(102,"通话");
Student s3=new Student(102,"重地");
Student s4=new Student(100,"asd");
System.out.println(s.hashCode());//460141958
System.out.println(s4.hashCode());//1163157884
h.add(s);
h.add(s2);
h.add(s3);
h.add(s4);
System.out.println(h);
}
}
2.TreeSet
TreeSet
可以给Set集合中元素按照指定方式排序;存储的对象必须实现Comparable
接口;TreeSet
底层数据机构是二叉树(红黑树是一种自平衡的二叉树)
package collectionapi.set;
import java.util.TreeSet;
public class TreeSetDemo {
/*
Set不能存储重复元素
TreeSet 可以按照元素的自然顺序排序
底层是红黑树
*/
public static void main(String[] args) {
TreeSet<Integer> t=new TreeSet();
t.add(3);
t.add(6);
t.add(2);
t.add(4);
System.out.println(t);
}
}
package collectionapi.set;
import java.util.Objects;
public class Student implements Comparable<Student> {
private int num;
private String name;
public Student(int num, String name) {
this.num = num;
this.name = name;
}
@Override
public String toString() {
return "学生{" +
"学号=" + num +
", 姓名='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return num == student.num &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(num, name);
}
@Override
public int compareTo(Student o) {
return 0;
}
}
package collectionapi.set;
import java.util.TreeSet;
public class TreeSetDemo2 {
public static void main(String[] args) {
/*
Set不能存储重复元素
TreeSet可以按照元素的自然顺序排列
底层是红黑树
*/
TreeSet<Student> t=new TreeSet<>();
Student s1 = new Student(101,"bim");
Student s2 = new Student(102,"通话1");
Student s3 = new Student(102,"重地");
Student s4 = new Student(101,"aim");
t.add(s1);
t.add(s2);
t.add(s3);
t.add(s4);
System.out.println(t);
}
}
3两种遍历方式
增强for
循环和迭代器(iterator)
package collectionapi.set;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetDemo3 {
public static void main(String[] args) {
/*
Set 不能存储重复元素
TreeSet 可以按照元素的自然顺序排序
底层是红黑树
*/
TreeSet<String> tset = new TreeSet<String>();
tset.add("b");
tset.add("a");
tset.add("d");
tset.add("c");
tset.add("x");
/*
* Set遍历方式
*/
//tset.stream().forEach((a)->System.out.print(a));
/* for (String t : tset) {
System.out.println(t);
}*/
Iterator<String> it = tset.iterator();
while(it.hasNext()){
String e = it.next();
System.out.println(e);
}
}
}
四.Map接口
(1)映射(map)是一个存储键、键值对的对象,给定一个键,可以查询得到它的值,键和值都可以是对象
(2)键必须是唯一的,值可以重复(Map接口映射唯一的键到值)
(3)有些映射可以接收null键和null值,而有的不行
(4)下面的接口支持映射:
Map接口 映射唯一关键字给值
Map.Entry接口 描述映射中的元素(关键字/值对),这是Map的一个内部类
SortedMap接口 扩展Map以便关键字按升序保持
(5)键(Key)是以后用于检索值的对象,给定一个键和一个值,可以存储这个值到一个Map对象中,以后可以
使用对应的键来检索它
(6)Map接口定义的方法:
int size()
存储的键值对的个数
boolean isEmpty()
判断容器中是不是空的
boolean containsKey()
判断容器中是否包含对应的键
boolean containsValue()
判断容器中是否包含指定的值
V get(Object value)
根据键来获取对应的值
V put(K key,V value)
把键值对数据添加到Map容器中
V remove(Object key)
删除Map容器中对应的key
Collection<V> values()
获取Map容器中所有的值
Set<Map.Entry<K,V>>entrySet()
返回包含的映射关系的Set视图
(7)Map.Entry
接口代表映射项(键值对)类型,是Map的嵌套类型
(8)Map接口定义的entrySet()方法返回包含映射项Entry的集合(Set),
集合中元素是Map.Entry类型(键值对封装在Map.Entry实现类对象中,然后把多个Entry实现类对象
放到Set容器中。)
(9)Map.Entry
接口定义的方法:
K getKey()
V getValue()
V setValue(V value)
1.HashMap及常用API
(1)HashMap
类是基于哈希表的Map接口的实现,并允许使用null键和null值
(2)构造方法:
HashMap()
HashMap(Map m)
HashMap(int capacity)
HashMap(int capacity,float fillRatio) fillRatio:
加载因子
(3)HashMap
实现Map并扩展AbstractMap,本身并没有增加任何新的方法
(4)散列映射不保证它的元素的顺序,元素加入散列映射的顺序并不一定是他们被迭代读出的顺序
(5) HashMap
中元素的key值不能重复,即彼此调用equals方法,返回为false。排列顺序是不固定的
package collectionapi.map;
import java.util.HashMap;
public class HashMapDemo {
public static void main(String[] args) {
/*
Map集合
键 值对存储
键不能重复,值可以重复
HashMap
键是无序的
可以存储一个为null的键
*/
HashMap<String,String> map = new HashMap<>();
map.put("a","a");
map.put("a","b");//如果有重复的键,后面值会把前面的覆盖掉
map.put("b","b");
map.put("p","b");
map.put(null,"c");
map.put(null,"n");
//map.remove("a");
//map.clear();
System.out.println(map.containsKey("c"));
System.out.println(map.containsValue("b"));
System.out.println(map.isEmpty());
System.out.println(map.size());
System.out.println(map.get("p"));
System.out.println(map);
}
}
package collectionapi.map;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.Set;
public class HashMapDemo2 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("a","a");
map.put("c","c");
map.put("b","b");
map.put("p","p");
/*
Map 集合比遍历
*/
//map.forEach((k,v)->System.out.println(k+":"+v));
/*
keySet();先获取到map中所有的键,存储到Set集合中
再对Set集合进行遍历,通过每次拿到key去获得对应的值
*/
/* Set<String> keyset = map.keySet();
for(String key : keyset){
System.out.println(key+":"+map.get(key));
}*/
//Collection<String> list = map.values();
//System.out.println(list);
/*
entrySet() 将map集合中的键,值对封装到一个Entry对象中
*/
Set<Entry<String, String>> entrySet = map.entrySet();
/* for(Entry<String, String> entry : entrySet){
System.out.println(entry.getKey()+":"+entry.getValue());
}*/
Iterator<Entry<String, String>> it = entrySet.iterator();
while(it.hasNext()){
Entry<String,String> entry = it.next();
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
2.TreeMap及常用API
TreeMap
中所有的元素都保持着某种固定的顺序,如果需要得到一个有序的Map就应该使用TreeMap
,key值所在类必须实现Comparable
接口。
TreeMap
适用于按自然顺序或自定义顺序遍历键(key)。TreeMap
根据key值排序,key值需要实现Comparable
接口,重写compareTo
方法。TreeMap
根据compareTo
的逻辑,对key进行排序。键是红黑树结构,可以保证键的排序和唯一性
package collectionapi.map;
import java.util.Hashtable;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
/*
键值对
键不重复
可以根据键的自然顺序排序, 指定的键的类型的类必需实现Comparable接口 ,排序使用
*/
TreeMap<Integer,String> tmap = new TreeMap<>();
tmap.put(2, "a");
tmap.put(1, "b");
tmap.put(1, "c");
tmap.put(3, "d");
System.out.println(tmap);
/*
无序的
初始容量是11
线程安全的
不允许存储为null的键
*/
Hashtable<String,String> ht = new Hashtable<>();
ht.put("a", "a");
ht.put("a", "b");
ht.put("c", "c");
ht.put(null, "d");
System.out.println(ht);
}
}
3.Map集合的遍历
方式1:根据键找值
- 获取所有键的集合
- 遍历键的集合,获取到每一个键
- 根据键找值
方式2:根据键值对对象找键和值
- 获取所有键值对对象的集合
- 遍历键值对对象的集合,获取到每一个键值对对象
- 根据键值对对象找键和值
4.Collections类
-
是集合类的工具类,与数组的工具类Arrays类似
-
定义了大量静态方法
package collectionapi.map;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
list.add("x");
Collections.addAll(list,"a","b","c","d");
System.out.println(Collections.binarySearch(list,"c"));
ArrayList<String> list1=new ArrayList<>();
list1.add("a");
list1.add("b");
list1.add("c");
list1.add("d");
ArrayList<String> list2=new ArrayList<>();
list2.add("x");
list2.add("y");
list2.add("z");
Collections.copy(list1,list2);//要求目标集合的size不能小于sec源集合的size
System.out.println(list1);
/*List<Object> l=Collections.emptyList();
l.add("a");
l.add("a");*/
Collections.fill(list1,"K");
System.out.println(Collections.max(list1));
Collections.replaceAll(list1,"x","X");
Collections.reverse(list1);
Collections.swap(list1,0,2);
System.out.println(list1);
}
}
创作不易,大佬们留步… 动起可爱的双手,来个赞再走呗 (๑◕ܫ←๑)