Java 容器
数组本身就是一种容器,可以在其中放置对象和基本数据类型
数组的优势:简单的线性序列,可以快速的访问数组元素,效率高。
数组的劣势:不够灵活,容量要事先定义好,不能随着需求的变化而扩容。
1. 概念
2. 泛型
泛型是JDK1.5以后增加的,它可以帮助我们建立类型安全的集合。
泛型的本质就是“数据类型的参数化”
eg:
package com.guoqiang;
public class TestGeneric {
public static void main(String[] args) {
MyCollection<String> mc = new MyCollection<String>(); // String:实参
mc.set("this", 0);
mc.set(888, 1); // 报错
Integer a = (Integer) mc.get(1); //报错:String无法转为int
String b = (String) mc.get(0);
}
}
class MyCollection<E> { // E 形参
Object[] objs = new Object[5];
public void set(E obj, int index) {
objs[index] = obj;
}
public E get(int index) {
return (E)objs[index];
}
}
3. Collection interface
package com.guoqiang;
import java.util.*;
/**
* 测试Collection接口中的方法
*/
public class TestList {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
// size() isEmpty()
System.out.println(c.size());
System.out.println(c.isEmpty());
c.add("String1");
c.add("String2");
System.out.println(c); // 调用了toString方法
System.out.println(c.size());
// contains()
System.out.println(c.contains("String2"));
System.out.println(c.contains("String3"));
// remove()
c.remove("String1"); // 对象还在,但是容器中没有,即从容器中拿出 容器中存放的是Object的地址
System.out.println(c);
// toArray()
Object[] objects = c.toArray();
System.out.println(objects);
// clear()
c.clear();
System.out.println(c.size());
}
}
两个容器之间的操作:
boolean addAll(Collection c); //将容器c中的所有元素增加的本容器
boolean removeAll(Collection c); // 移除本容器中和容器c中都包含的元素,移除交集元素
boolean retainAll(Collection c); // 取本容器和c容器之间的交集元素,移除非交集元素
4. List interface
List是有序、可重复的容器
有序:List中的每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制元素。
可重复:List允许加入重复的元素,更确切的讲,List通常满足e1.equal(e2)的两个元素e1,e2重复加入容器。
List接口中常用的实现类有3个:ArrayList、LinkedList和Vector
a、ArrayList底层用的数组,LinkedList底层用的链表,Vector底层用的是数组(线程安全)
package com.guoqiang;
import java.util.*;
/**
* 测试Collection接口中的方法
*/
public class TestList {
public static void main(String[] args) {
test03();
}
public static void test03() {
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
System.out.println(list);
// add的重载方法,指定位置插入
list.add(2,"ME"); // 在index为2的地方插入一个,后面元素依次后移
System.out.println(list);
// 删除指定位置的元素
list.remove(2);
System.out.println(list);
// 替换指定位置处的元素
list.set(2,"MMME");
System.out.println(list);
// 得到指定位置的值
System.out.println(list.get(2));
// 返回从左到右找到的第一个目标
System.out.println(list.indexOf("MMME"));
// 返回从右到左找到的第一个目标
System.out.println(list.lastIndexOf("D"));
}
}
ArrayList 底层用数组实现的存储(查询效率高,增删效率低(使用LinkedList),线程不安全(使用Vector))一般使用它。
ArrayList可以存放任意数量的元素,底层实现数组的扩容。
b、LinkedList
c、Vector
- 需要线程安全,效率低,
public synchronized int indexOf(Object o, int index); 容器对象多个线程共享的时候,用vector。
不存在线程安全问题时,查找比较多,用ArrayList
与ArrayList差不多,更加注重线程安全。
5. Map interface
Map常用的方法:
常用的实现类 HashMap
TreeMap: 排序的时候用,底层采用了红黑二叉树
HashMap 线程不安全,允许key和value为null
HashTable 线程安全,效率第,不允许key和value为null
6. Set Interface
实现类HashSet
HashSet 的底层就是一个HashMap:
public HashSet() {
map = new HashMap<>();
}