目录
一.集合框架的概述
1.集合。数组都是对多个数组进行存储操作的结构,简称java容器
说明:此时的存储,主要指内存层面的存储,不涉及到持久化的存储(.txt .jpg .avi.数据库中)
2.数组在存储多个数据方面的特点:
》一旦初始化以后,长度就确定了
》比如String[] arr;int[] arr1;元素的类型就确定了,我们也就只能操作指定数据的类型。不过有多态性
缺点;
》一旦初始化以后长度就不可以修改了
》数组中提供的方法非常有限,对于添加,删除,插入数据等操作非常不便,同时效率不高
》获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
》数组存储数据的特点:有序,可重复。对于无序,不可重复的需求,数组不能满足的。
3.集合框架
java集合可分为collection 和map两种体系
Collection 接口:单列数据,定义了获取一组对象的方法集合
list :元素有序,可重复的集合 动态数组
ArrayList,LinkedList,Vector
set:元素无序,不可重复的集合 集合
HashSet,LinkedHashSet,TreeSet
Map接口:双列数据,保存具有映射关系“key-value”的集合
HashMap,LinkerHashMap,TreeMap,Hashtable,Properties
二.集合
<一> Collenctions 接口
1.Collections接口常用方法
//add(Object e ):将元素e添加到集合coll中
//size():获取添加的元素的个数
//addAll(Collection coll); 将coll集合中的元素添加到当前的集合中
//clear();清空集合
//isEmpty();判断当前集合是否为空
//contains(Object obj):判断当前集合中是否包含obj
//containsAll(Collection coll1):判断行惨coll1中的所有元素是否都存在与当前集合中
//remove 方法调用equals方法判断后移除
//removeAll(Collection coll)从当前集合中移除coll共有的元素 差集
//retainAll(Collection coll)保留当前集合与coll共有的元素,交集
//equals(Object object) 判断当前集合和行参集合的元素相同
//hashcode();返回当前对象的哈希值
//toArray();集合--->数组
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class CollectionTest {
public static void main(String[] args){
Collection coll1 = new ArrayList();
//add(Object e ):将元素e添加到集合coll中
coll1.add("AA");
coll1.add(123);
coll1.add(new String("Tom"));
coll1.add(new Person("jerry",20));
//size():获取添加的元素的个数
System.out.println(coll1.size());
//addAll(Collection coll); 将coll集合中的元素添加到当前的集合中
//Collection coll = new ArrayList();
//coll.add(111);
Collection coll = Arrays.asList(123,457);
System.out.println(coll.size());
System.out.println(coll);
//clear();清空集合
//coll.clear();
//isEmpty();判断当前集合是否为空
System.out.println(coll.isEmpty());
//contains(Object obj):判断当前集合中是否包含obj 会调用obj对象所在类的equals()方法
//向Collection接口的实现类的对象中添加obj时,要求obj所在类要重写equals()方法
boolean contains = coll1.contains(123);
System.out.println("contains :"+contains);
System.out.println("contains 调用String equals方法 :"+coll1.contains(new String("Tom")));//注意此时又新建了一个对象两个对象地址值不一样
System.out.println("contains 调用Object equals方法 :"+coll1.contains(new Person("jerry",20)));
//注意此时第二个是true,所以调用的是String中的equals方法,但是第三个是false说明调用的时object类中的equals方法相当于==
//containsAll(Collection coll1):判断行惨coll1中的所有元素是否都存在与当前集合中
boolean contains1 = coll1.containsAll(coll);
System.out.println("contains1 :"+contains1);
//remove 方法调用equals方法判断后移除
coll1.remove(123); //
System.out.println("remove 方法"+coll1);
//removeAll(Collection coll)从当前集合中移除coll共有的元素 差集
//retainAll(Collection coll)保留当前集合与coll共有的元素,交集
//equals(Object object) 判断当前集合和行参集合的元素相同
//hashcode();返回当前对象的哈希值
System.out.println("哈希值: "+coll1.hashCode());
//toArray();集合--->数组
Object[] arr = coll1.toArray();
for(int i =0;i<arr.length;i++){
System.out.println("集合-->数组 : "+arr[i]);
}
//拓展:数组--》集合 调用Arrays类中的asList静态方法
List<String> list = Arrays.asList(new String[]{"jea","eer","aadf"});
System.out.println(list);
}
}
class Person{
private String name;
private int age;
public Person(){
}
public Person(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 age(){
return age;
}
public void setAge(int age){
this.age= age;
}
@Override
public String toString(){
return "Person{" + "name=" + name +'\''+", age = "+age +'}';
}
}
2.集合遍历
Iterator遍历Collection
for-each循环遍历数组和集合
//for(集合中元素的类型局部变量:集合对象){}
//for(数组元素类型数组变量:数组对象){}
for(Object obj:coll){
System.out.println(obj);
}
(一)list 接口
动态数组
三个具体实现类异同
ArrayList , 作为List接口的主要实现类 ,线程不安全,效率高 底层Object[]数组 elementData存储
ArrayList的源码分析;jdk7 类似单例饿汉式
ArrayList list=new ArrayList();//底层创建了长度是10的Object[]数组elementData
list.add(123);//element Data[0]=new Integer(123)
list.add(11);//如果此次添加导致底层elementData数组容量不构,则扩容。默认情况下,扩容 为原来容量的1.5倍
//同时需要将原有的数组中的数据复制到新的数组中去
//建议使用带参的构造器ArrayList list=new ArrayList(10);
Jdk8类似单例的懒汉式,延迟数组创建,节省内存
ArrayList list=new ArrayList();//底层Object[] elementData初始话为{},并没有创建长度为10的数组
list.add(123);//第一次调用add,底层才创建了长度10的数组,并将数据123添加到elementData[0]
后续的添加和扩容操作都一样
LinkedList ,对于频繁的插入和删除操作,使用此效率比ArrayList高 底层是使用双向链表存储
LinkedList list = new LinkedList();内部声明了Node类型,的first和Last属性,默认值为null,其中Node定义为:体现了LinkedLsit的双向链表的说法
private static class Node<E>{
E item;
Node<E> next;
Node<E> prev;
Node (Node<E> prev,E element,Node<E> next){
this.item = element;
this.next = next;
this.prev = prev;
}
}
Vector 作为List接口的古老实现类 ,线程安全,效率低 底层Object[]数组elementData存储
同;三个类都实现了List接口,存储数据的特点相同,存储有序,可重复的数据
packagecom.example.lisr;
/*
List接口中的常用方法
void add(int index,Object obj):在index位置插入obj元素
boolean addAll(int index,Collection eles):在index位置插入eles中的所有元素添加
Object get(int index):获取index位置的元素
int indexOf(Object obj):返回obj在当前集合中首次出现的位置若不存在返回-1
int LastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
Object remove(intindex):删除指定index位置的元素,并返回此元素
Object set(int index,Object elee):设置指定index位置的元素为elee
ListsubList(int from Index,int to Index):返回从fromIndex到toIndex位置的左闭右开子集合
总结常用方法
增:add(Object obj);
删:remove(int index)/remove(Object obj)
改:set(int index,Object ele)
查:get(int index) indexOf(Object obj)
插:add(int index,Onject obj)
长度:size()
遍历:
1.Iterator迭代器方式
while(iterator.hasNext()){
Object obj=iterator.next();
System.out.println("遍历:"+obj);
2.for-each循环
for(Object obj:list){
System.out.println(obj);
}
3.普通的循环
*/
importjava.util.ArrayList;
importjava.util.Arrays;
importjava.util.Date;
importjava.util.List;
public class List Test{
public static void main(String[] a){
ArrayList list=new ArrayList();
list.add(123);
list.add(456);
list.add("AA");
list.add(newDate());
list.add(456);
System.out.println(list);
list.add(1,"BB");
System.out.println("插入"+list);
Listlist1=Arrays.asList(1,2,3);
list.addAll(list1);
System.out.println("addall"+list+list.get(2));
}
}
(二)set接口
三个实现类 无序的不可重复的
HashSet: 作为Set接口的主要实现类:线程不安全的:可以存储null值
1.无序性:不等于随机性,只是不是按照数组元素索引顺序添加
2.不可重复性:保证添加的元素按照equals()判断,不能返回true,即相同的元素只能添加一个
数组加链表的结构
3.添加数据的过程 以HashSet为例
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法,计算出在HashSet底层数组中的存放位置(即索引位置),
判断数组此位置上是否已经有元素,
如果此位置没有其他元 素,则元素a添加成功
如果此位置上有其他元素b(或者以链表形式存在多个元素),则比较a与b的哈希值:
如果哈希值不相同,则元素添加成功,以链表的形式存储
如果哈希值相同,进而需要调用元素a所在类的equal()方法;
equals()返回true,元素a添加失败
Equals()返回false,则元素a添加成功,以链表形式存储
4.set接口中没有额外定义新的方法,使用的是collection 中声明的过的方法
5.要求:向set中添加的数据,其所在的类一定要重写hashCode()和equals()
要求:重写的hashCode()和equals()方法尽可能保持一致性:相等的对象必须具有相等的 散列码
LinkedHashSet :作为HashSet的子类,遍历其内部数据时,可以按照添加的顺序去遍历
TreeSet:可以按照添加对象的指定属性进行排序。
1.向TreeSet中添加,只能添加某一个类的对象,不能添加不同类的对象
2.两种排序方式:自然排序(实现Comparable接口)和定制排序(Comparator接口)
底层二叉树,中序遍历
3.自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals(),
(在元素对象中继承Comparable接口并重写compareTo方法,来针对性的比较)
Public int compareTo(Objecto){
if(o instanceof Empolyee){
Empolyeee=(Empolyee)o;
returnthis.name.compareTo(e.name);
}
//return0;
thrownewRuntimeException("传入数据类型不一致");
}
4.定制排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals()
(新建对象Comparator对象并重写方法,形参的方式传入到TreeSet)
Comparator com=new Comparator(){
@Override
Publicint compare(Objecto1,Objecto2){
if(o1 instanceof Empolyee&&o2 instanceof Empolyee){
MyDateb1=((Empolyee)o1).getBirthday();
MyDateb2=((Empolyee)o2).getBirthday();
Return b1.getYear()-b2.getYear();
}
//return0;
Throw new Runtime Exception("传入数据类型不一致");
}
};
TreeSet set=new TreeSet(com);
set接口中没有额外定义新的方法,都是使用Collection 中的方法
无序性:不等于随机性,只是不是按照数组元素索引顺序添加
不可重复性:保证添加的元素按照equals()判断,不能返回true,即相同的元素只能添加一个
<二>map 接口
Map:双列数据,存储key-value对数据我,类似函数y =f(x)
HashMap:作为map的主要实现类 :线程不安全,效率高 存储null的key和value
Jdk7 数组+链表
Jdk8 数组+链表+红黑树
HashMap底层实现原理 jdk7
HashMap map = new HashMap();
在实例化以后,底层创建了长度为16的一维数组Entry[] table.
map.put(key1,value1);
首先,计算key1所在类的hashcode方法,计算key1哈希值,通过某种算法计算以后得到Entry数组中的存放位置。
判断数组此位置上是否已经有元素,
如果此位置没有其他元 素,则元素key1-value1添加成功
如果此位置上有其他元素b(或者以链表形式存在多个元素),则比较a与b的哈希值:
如果哈希值不相同,则元素添加成功,以链表的形式存储
如果哈希值相同,进而需要调用元素key1所在类的equal()方法;
equals()返回true,元素key1-value1添加失败
Equals()返回false,则元素key1-value1添加成功,使用value1 替换value2 以链表形式存储
Jdk8
1.new HashMap 底层没有创建一个长度为16的数组
2.底层数组为Node[],而非Entry[]
3.首次调用put()方法,底层创建长度为16的数组
4.jdk8 数组+列表+红黑树
当数组的某一个索引位置上的元素以链表形式存在的数据个数> 8且当前数组的长度>64此时此索引位置上的所有数据改为使用红黑树存储
LinkedHashMap:
保证在遍历map元素时,可以按照添加的顺序实现遍历。在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素
对于频繁的遍历操作,此类执行效率高于HashMap
TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑可以的自 然排序,底层是使用红黑树
想TreeMap中添加key-value,要求key必须是同一个类创建的对象
因为要按照key进行排序:自然排序,定制排序
排序方式参考treeSet;
HashTable:古老的实现类:线程安全,效率低 不能存储null的key和value
Properties:常用来处理配置文件。Key-value都是String类型
二。map结构i的理解
map中的key 无序的,不可重复的,使用set存储所有的key ,以HashMap为例其所在的类一定要重写hashCode()和equals()
Map中的value :无序的,不可重复,使用Collection 存储所有的value 要求obj所在类要重写equals()方法
一个键值对,key-value构成了一个Entry对象
Map中的entry:无序的,不可重复的,使用set存储所有的entry
常用的方法:
Package com.example.maptest;
Import java.util.HashMap;
Import java.util.Map;
Public class MapTest{
Public static void main(String[]args){
Map map=new HashMap();
//添加
map.put("AA",123);
map.put("BB",456);
map.put("CC",789);
//修改
map.put("AA",124);
System.out.println(map);
Mapmap1=newHashMap();
map1.put("CC",123);
map1.put("DD",123);
map.putAll(map1);
//Objectremove(Objectkey)移除指定key的key-value对,并返回value
Object value=map.remove("CC");
System.out.println(value);
System.out.println(map);
//voidclear();清空当前map
//map.clear();
//System.out.println(map.size());
//Objectget(Objectkey):获取指定key对应的value
System.out.println("查询:"+map.get("DD"));
//booleancontainsKey(Objectkey):是否包含指定的key
//booleancontainsValue(Objectvalue):是否包含指定的value
//intsize()返回map中key-value对的个数
//booleanisEmpty():判断当前map是否为空
//booleanequals(objectobj);判断当前map和参数对象obj是否相等
}
}