一、Collection和Map的简单结构图
二、容器的介绍与比较
1、Collection容器:一组各自独立的元素集合
(1)List、Set对比
List:有序可重复的元素集合
Set:无序不可重复的元素集合,底层实现为Map
(2)ArrayList、LinkedList、Vector对比
ArrayList、LinkedList、Vector均为List接口的实现类
ArrayList:底层实现为数组,线程不安全,查询效率高,插入删除效率低
LinkedList:底层实现为链表,线程不安全,查询效率低,插入删除效率高
Vector:底层实现为数组,线程安全
(3)Set与HashSet使用方法区别
Set是接口,HashSet是Set的一个实现子类。
Set变量实现时发生多态,需要指向具体的实现类对象,可以是HashSet类对象、也可以是其他子类对象,HashSet变量实现时创建的是HashSet类对象
定义Set变量,实例化时创建需要的子类对象,后续如果需要修改存储的类型,直接修改实例化时创建的对象就可以,修改方便
2、Map容器:以key-value(键值对)形式存储数据,key允许重复,底层实现形式:数组+链表
(1)HashMap、HashTable对比
HashMap:基于哈希表;线程不安全;没有contains()方法;key值不重复,key和value值允许出现null值;重新计算hashCode
HashTable:基于哈希表;线程安全;有contains()方法;key值不重复,key和value都不允许出现null值;直接使用对象的hashCode
(2)Map与HashMap使用方法区别
Map是接口,HashMap是Map的一个实现子类。
Map变量实现时发生多态,需要指向具体的实现类对象,可以是HashMap类对象、也可以是其他子类对象,HashMap变量实现时创建的是HashMap类对象
定义Map变量,实例化时创建需要的子类对象,后续如果需要修改存储的类型,直接修改实例化时创建的对象就可以,修改方便
三、容器的使用
1、容器的方法调用
(1)Map接口类方法使用
import java.util.HashMap;
import java.util.Map;
/**
* Map接口类的方法使用
* put、get、remove、putAll、constaintKey、constaintValue、clear、size、isEmpty
*
*/
public class MapTest {
public static void main(String[] args) {
Map map = new HashMap();
//put(key,value):向容器中添加键值对,key值不可以重复,若key重复,后面新添加的value会覆盖前面的value
map.put("姓名", "张三");
map.put("部门", "信息部");
map.put("姓名", "李四");
map.put("单位", "信息部");
//get(key):根据key从元素中获取value,返会value对象
String name = (String) map.get("姓名");
System.out.println(name);
//size():返回容器中键值对的个数
int size = map.size();
System.out.println(size);
//containsKey(key):判断容器中是否包含与参数key相等的key,返回boolean,底层比较实用equals
boolean b1 = map.containsKey("姓名");
System.out.println(b1);
//containsValue(value):判断容器中是否包含与参数value相等的value,返回boolean,底层比较实用equals
boolean b2 = map.containsValue("信息部");
System.out.println(b2);
//remove(key):删除容器中key等于参数key的键值对
map.remove("单位");
//isEmpty():判断容器中是否有元素,若存在元素,则返回false,若不存在元素,返回true
boolean b3 = map.isEmpty();
System.out.println(b3);
//putAll(Map m):将参数容器m中的所有元素添加到当前容器中
Map m = new HashMap();
m.put("薪资", 3000);
m.put("年龄", 20);
map.putAll(m);
System.out.println(map.get("年龄"));
//clear():清空容器中所有元素
map.clear();
System.out.println(map.size());
}
}
(2)Set接口类方法使用
import java.util.HashSet;
import java.util.Set;
/**
* Set接口类方式使用
* add,addAll,size,contains,containsAll,isEmpty,remove,removaAll,clear
*
*/
public class SetTest {
public static void main(String[] args) {
Set set = new HashSet();
//add(e):向Set集合中添加元素,添加元素不可重复
set.add("aaa");
set.add("bbb");
//addAll(Collection c):将参数集合c中的所有元素添加到当前集合set中
Set set1 = new HashSet();
set1.add("ccc");
set.addAll(set1);
//size():返回集合中的元素个数
System.out.println(set.size());
//contains(e):判断Set集合中是否包含e对象,若包含返回true,否则返回false
boolean b = set.contains("aaa");
System.out.println(b);
//containsAll(Collect c):判断集合Set中是否包含参数set集合,若包含返回true,否则返回false
boolean b1 = set.containsAll(set1);
System.out.println(b1);
//isEmpty():判断集合中是否有元素,若存在元素,则返回false,若不存在元素,返回true
boolean b2 = set.isEmpty();
System.out.println(b2);
//remove(e):将元素e从结合中移除
set.remove("aaa");
//removeAll(Collect c):将当前集合中所有包含在集合c中的元素全部移除
set.removeAll(set1);
//clear():清空集合中的所有元素
set.clear();
System.out.println(set.size());
}
}
(3)List接口方法使用
```java
import java.util.ArrayList;
import java.util.List;
/**
* List接口方法使用
* add、addAll、size、get、set、remove、clear、isEmpty、contains
*
*/
public class ListTest {
public static void main(String[] args) {
List list = new ArrayList();
//add(e):向List容器末尾添加元素
list.add("aaa");
list.add("bbb");
//add(index, element):向List容器中index索引位置插入元素
list.add(1, "ccc");
//addAll(c):在List容器末尾添加参数容器c中所有元素
List list1 = new ArrayList();
list1.add("测试addAll");
list.addAll(list1);
//addAll(index, c):在List容器index索引位置插入参数容器c中所有元素
list.addAll(0, list1);
//size():返回集合中的元素个数
int size = list.size();
System.out.println(size);
//get(index):查找索引index位置的元素并返回
String str = (String) list.get(2);
System.out.println(str);
//set(index, element):将容器中index位置的元素修改为element
list.set(0, "修改数据");
System.out.println(list.get(0));
//remove(index):从容器中移除索引位置index的元素
list.remove(1);
System.out.println(list.get(1));
//remove(o):从容器中移除元素o
list.remove("aaa");
//clear():清空容器中所有元素
list.clear();
//contains(o):判断容器中是否包含元素o,若包含返回ture,否则返回false
boolean b1 = list.contains("ccc");
System.out.println(b1);
//constainsAll(c):判断容器中是否包含参数容器中的所有元素,若包含返回ture,否则返回false
boolean b2 = list.containsAll(list1);
System.out.println(b2);
//isEmpty():判断容器中是否有元素,若存在元素返回false,否则返回true
boolean b3 = list.isEmpty();
System.out.println(b3);
}
}
2、自定义实现ArrayList类、LinkedList类(加深理解)
(1)自定义实现ArrayList类中主要方法
```java
package cn.cjy.collection;
import java.lang.reflect.Array;
/**
* 自定义实现ArrayList
*/
public class MyArrayList {
private Object[] elementData;
private int size;
public int size(){ //获取容器元素个数
return size;
}
public boolean isEmpty(){ //判断容器中为空
return size==0;
}
public MyArrayList(){
this(3);
}
public MyArrayList(int initialCapacity){
if(initialCapacity<0){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
elementData = new Object[initialCapacity];
}
//向容器中添加元素
public void add(Object obj){
ensureCapacity();//数组扩容
elementData[size++] = obj;
}
//向容器中指定位置插入元素
public void add(int index,Object obj){
rangeCheck(index);
ensureCapacity();
System.arraycopy(elementData, index, elementData, index+1, size-index);
elementData[index] = obj;
size++;
}
//修改容器中指定位置元素
public void set(int index,Object obj){
rangeCheck(index);
elementData[index] = obj;
}
//移除容易中指定位置元素
public void remove(int index){
rangeCheck(index);
int noveNum = size-index-1;
if(noveNum>0){
System.arraycopy(elementData, index+1, elementData, index, noveNum);
}
elementData[size--]=null;
}
//移除容器中的等于obj的元素
public void remove(Object obj){
for(int i=0;i<size;i++){
if(get(i).equals(obj)){
remove(i);
}
}
}
//获取容器中指定位置元素
public Object get(int index){
rangeCheck(index);
return elementData[index];
}
//检查索引是否合法
private void rangeCheck(int index){
if(index<0 || index>=size){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//数组扩容
private void ensureCapacity(){
if(size == elementData.length){
Object[] newArray = new Object[size*2+1];
System.arraycopy(elementData, 0, newArray, 0, elementData.length);
elementData = newArray;
}
}
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add("测试");
list.add("测试2");
list.add("测试3");
list.add("测试4");
list.add(2,"我是中途加进来的");
list.remove(0);
list.set(2, "我是修改");
list.remove("测试4");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}
(2)自定义实现LinkedList类中主要方法
package cn.cjy.collection;
/**
* 自定义双向链表集合 LinkedList
*/
public class MyLinkedList {
private MyNode first;
private MyNode last;
private int size;
public int size(){ //返回容器中元素个数
return size;
}
public MyLinkedList(){
}
//获取指定位置元素
public Object get(int index){
rangeCheck(index);
MyNode temp = node(index);
if(temp != null){
return temp.getNode();
}
return null;
}
public MyNode node(int index){ //根据索引遍历找对象
MyNode temp=null;
if(first != null){
if(index < (size>>1)){ //如果index小于size的一半,从前往后找,否则从后往前找
temp = first;
for(int i=0;i<index;i++){
temp = temp.getNext();
}
}else{
temp = last;
for(int i=size-1; i>index; i--){
temp = temp.getPrevious();
}
}
}
return temp;
}
//向容器中添加元素
public void add(Object obj){
MyNode myNode = new MyNode();
if(first == null){
myNode.setNode(obj);
first = myNode;
last = myNode;
}else{
myNode.setPrevious(last);
myNode.setNode(obj);
last.setNext(myNode);
last = myNode;
}
size++;
}
//向容器中指定位置插入元素
public void add(int index,Object obj){
rangeCheck(index);
MyNode temp = node(index); //找到节点
MyNode myNode = new MyNode();//创建新节点
if(temp !=null){
myNode.setPrevious(temp.getPrevious());
myNode.setNode(obj);
myNode.setNext(temp);
temp.getPrevious().setNext(myNode);//原index节点的上节点的下节点改为新节点
temp.setPrevious(myNode); //原index节点的上节点设为新节点
size++;
}
}
//修改容器中指定位置元素
public void set(int index,Object obj){
rangeCheck(index);
MyNode temp = node(index); //找到节点
if(temp != null){
temp.setNode(obj);
}
}
//移指定位置元素
public void remove(int index){
rangeCheck(index);
MyNode temp = node(index); //找到节点
if(temp != null){
if(first == temp){
if(first.getNext() != null){
first.getNext().setPrevious(null);
first = first.getNext();
}else{
first = null;
last = null;
}
}else if(last == temp){
if(last.getPrevious() != null){
last.getPrevious().setPrevious(null);
last = last.getPrevious();
}else{
first = null;
last = null;
}
}else{
temp.getPrevious().setNext(temp.getNext());
temp.getNext().setPrevious(temp.getPrevious());
}
size--;
}
}
public void rangeCheck(int index){ //检查索引是否合法
if(index<0 || index >= size){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
list.add("链表测试");
list.add("111");
list.add("222");
list.add(1,"test");
list.set(1,"test002");
System.out.println(list.get(1));
list.remove(1);
System.out.println(list.get(1));
//list.remove("链表测试");
//System.out.println(list.get(0));
}
}
3、迭代器遍历容器中的元素
(1)Set集合的遍历方式
package cn.cjy.collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* 迭代器遍历Set
*/
public class IteratorSet {
public static void main(String[] args) {
Set set = new HashSet();
set.add("语文");
set.add("数学");
set.add("英语");
//while循环遍历
Iterator itera = set.iterator();
while(itera.hasNext()){
String str = (String) itera.next();
System.out.println(str);
}
//for循环遍历
for(Iterator itera1 = set.iterator();itera1.hasNext();){
String str1 = (String) itera1.next();
System.out.println(str1);
}
}
}
(2)Map的2种遍历方式
package cn.cjy.collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* 迭代器遍历Map
*
*/
public class IteratorMap {
public static void main(String[] args) {
Map map = new HashMap();
map.put("姓名", "张三");
map.put("性别", "男");
map.put("部门", "信息部");
//遍历Map的第一种方式
Set<Entry> set1 = map.entrySet(); //将Map转换成存放键值对的Set集合
Iterator itera1 = set1.iterator();
while(itera1.hasNext()){
Entry entry = (Entry) itera1.next();
String str1 = (String) entry.getKey();
String str2 = (String) entry.getValue();
System.out.println(str1+":"+str2);
}
//遍历Map的第二种方式
Set set2 = map.keySet(); //将Map的键放入Set集合
Iterator itera2 = set2.iterator();
while(itera2.hasNext()){
String str1 = (String) itera2.next(); //获取键
String str2 = (String) map.get(str1); //获取值
System.out.println(str1+":"+str2);
}
}
}
(3)List的遍历方式
package cn.cjy.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* List的遍历方式
*/
public class IteratorList {
public static void main(String[] args) {
List list = new ArrayList();
list.add("语文");
list.add("数学");
list.add("英语");
//根据索引循环遍历
for(int i=0;i<list.size();i++){
String str = (String) list.get(i);
System.out.println(str);
}
//根据迭代器循环遍历
Iterator itera = list.iterator();
while(itera.hasNext()){
String str1 = (String) itera.next();
System.out.println(str1);
}
}
}
4、容器装载数据应用举例
(1)List
package cn.cjy.collection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* List<Map>存储数据
*/
public class MapStore {
public static void main(String[] args) {
List<Map> list = new ArrayList<Map>();
Map map1 = new HashMap();
map1.put("姓名", "张三");
map1.put("年龄", 20);
map1.put("入职日期", "2019-01-01");
Map map2 = new HashMap();
map2.put("姓名", "李四");
map2.put("年龄", 21);
map2.put("入职日期", "2018-01-01");
Map map3 = new HashMap();
map3.put("姓名", "王二");
map3.put("年龄", 22);
map3.put("入职日期", "2017-01-01");
list.add(map1);
list.add(map2);
list.add(map3);
for(Map m : list){
String name = (String) m.get("姓名");
int age = (Integer) m.get("年龄");
String inDate = (String) m.get("入职日期");
System.out.println(name+" "+age+" "+inDate);
}
}
}
(2)ArrayList存储数据
自定义一个实体类:Employee 列:姓名、年龄、入职日期。然后装载到 ArrayList容器中,最后增强for循环输出姓名
package cn.cjy.collection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Employee {
private String name; //姓名
private int age; //年龄
private Date inDate; //入职日期
public Employee(){
}
public Employee(String name, int age, String inDate) {
super();
this.name = name;
this.age = age;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
this.inDate = format.parse(inDate);
} catch (ParseException e) {
e.printStackTrace();
}
}
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 Date getInDate() {
return inDate;
}
public void setInDate(Date inDate) {
this.inDate = inDate;
}
}
package cn.cjy.collection;
import java.util.ArrayList;
import java.util.List;
/**
* ArrayList存储数据
*/
public class ArrayListStore {
public static void main(String[] args) {
Employee e1 = new Employee("张三", 20, "2019-01-01");
Employee e2 = new Employee("李四", 21, "2018-01-01");
Employee e3 = new Employee("王二", 22, "2017-01-01");
List<Employee> list = new ArrayList<Employee>();
list.add(e1);
list.add(e2);
list.add(e3);
for(Employee e : list){
System.out.println(e.getName());
}
}
}
四、补充
1、ArrayList中size与length的区别
size是ArrayList中元素的个数,length是数组长度,size<=length
2、System.arraycopy() 函数:复制数组
package cn.cjy.collection;
/**
* 使用System.arraycopy()函数复制数组
* System.arraycopy(src, srcPos, dest, destPos, length)
* src:源数组
* srcPos:源数组开始复制位置
* dest:目标数组
* destPos:目标数组开始放的位置
* length:复制的长度
*/
public class ArrayCopyTest {
public static void main(String[] args) {
String[] arr1 = new String[5];
arr1[0] = "测试数组复制";
String[] arr2 = new String[]{"aaa","bbb","ccc"};
System.arraycopy(arr2, 1, arr1, 1, 2);
for(int i=0;i<arr1.length;i++){
System.out.println(arr1[i]);
}
}
}
``