集合存储的是元素的地址。
package com.bjsxt.collection;
import com.bjsxt.demo.Gender;
import com.bjsxt.demo.Person;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
Collection collection=new ArrayList();//接口new实现类
System.out.println("集合是否为空:"+collection.isEmpty());
//(1)添加元素
collection.add("hello");
collection.add(new Date());
collection.add(123);
collection.add("hello");
collection.add(new Person("lisli",29, Gender.男));
System.out.println("集合是否为空:"+collection.isEmpty());
System.out.println("集合中元素的个数:"+collection.size());
System.out.println(collection);
System.out.println(collection.remove("hello")); //将第一个hello删除
//collection.clear();
System.out.println(collection);
System.out.println(collection.contains(123));
Collection collection1=new ArrayList();
collection1.add("world1");
collection1.add("world2");
collection1.add("world3");
collection.addAll(collection1);
System.out.println(collection);
//遍历集合
System.out.println("---------------------------------------");
for(Object obj:collection){
System.out.println(obj);//默认调用toString()方法
}
System.out.println("------------------自己使用迭代器遍历元素 hasNext() ,next()---------------------------");
Iterator ite= collection.iterator();
while(ite.hasNext()){ //true就说明集合中有数据,为false,说明集合中没有数据,可以退出循环
Object obj= ite.next();
System.out.println(obj);
}
}
}
package com.bjsxt.collection;
import com.bjsxt.demo.Gender;
import com.bjsxt.demo.Person;
import java.util.*;
public class Test2 {
public static void main(String[] args) {
Collection collection=new LinkedList();//接口new实现类
System.out.println("集合是否为空:"+collection.isEmpty());
//(1)添加元素
collection.add("hello");
collection.add(new Date());
collection.add(123);
collection.add("hello");
collection.add(new Person("lisli",29, Gender.男));
System.out.println("集合是否为空:"+collection.isEmpty());
System.out.println("集合中元素的个数:"+collection.size());
System.out.println(collection);
System.out.println(collection.remove("hello")); //将第一个hello删除
//collection.clear();
System.out.println(collection);
System.out.println(collection.contains(123));
Collection collection1=new LinkedList();
collection1.add("world1");
collection1.add("world2");
collection1.add("world3");
collection.addAll(collection1);
System.out.println(collection);
//遍历集合
System.out.println("---------------------------------------");
for(Object obj:collection){
System.out.println(obj);//默认调用toString()方法
}
System.out.println("------------------自己使用迭代器遍历元素 hasNext() ,next()---------------------------");
Iterator ite= collection.iterator();
while(ite.hasNext()){ //true就说明集合中有数据,为false,说明集合中没有数据,可以退出循环
Object obj= ite.next();
System.out.println(obj);
}
}
}
ArrayList是Object数组元素的封装
当调用ArrayList无参构造方法是创造一个ArrayList的对象。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //初始长度为0,在堆里开空间了
transient Object[] elementData; //声明一个Object类型的数组,并没有new对象
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //指向 是长度为0的那个数组
}
第一次调用add方法时,分配给集合的容量时10
private int size; //集合中元素的个数 ,默认值为0
private static final int DEFAULT_CAPACITY = 10;
public boolean add(E e) {
ensureCapacityInternal(size + 1); //调用本类中的方法
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {//minCapacity 的值为1
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//第一次调用add方法时执行
return Math.max(DEFAULT_CAPACITY, minCapacity); //return Math.max(10,1);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) { //计算出来的最小容量为10
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) //10-0>0?true 说明数组的长度已完全不够用
grow(minCapacity);
}
private void grow(int minCapacity) { //10
// overflow-conscious code
int oldCapacity = elementData.length; //oldCapacity= 0
int newCapacity = oldCapacity + (oldCapacity >> 1); //0+0 结果为 newCapacity=0
if (newCapacity - minCapacity < 0) //0-10<0 true
newCapacity = minCapacity; //newCapacity=10;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //数组拷贝
}
当第11次在添加集合元素时,空间容量会变成15,原理如下:
int newCapacity = oldCapacity + (oldCapacity >> 1);
总结:ArrayList的增删改查都是对底层的Object的类型数组的增删改查,
所以ArrayList的优点时:节省存储空间,按照索引查找效率高
缺点:删除,添加需要大量移动元素时,效率低下,按照内容查找元素,需要逐个判断,效率低下
LinkedList底层:
transient Node<E> first; //默认值均为null
transient Node<E> last;
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null); //当调用add方法时,new Node创建节点对象
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
//LinkedList中的私有静态内部类
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;
}
}
Linkedlist的优点:添加,删除元素不需要移动元素,效率高
缺点:每个元素的节点都存储了下一个元素的地址,占据了更多的空间,每个节点的地址不连续,所以按照索引查找也是分别不方便。
List接口:
package com.bjsxt.list;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
public class TestList {
public static void main(String[] args) {
List list=new ArrayList();
// List lits=new LinkedList();
list.add("hello");
list.add("world");
list.add(0,"java");
list.add(0,123);
// list.add(7,"sql");java.lang.IndexOutOfBoundsException: Index: 7, Size: 4
System.out.println(list);
// list.remove("world");
// list.remove(123); java.lang.IndexOutOfBoundsException: Index: 123, Size: 3
//list.remove(new Integer(123));
System.out.println(list);
System.out.println("获取元素:"+list.get(0)+"\t"+list.get(1));
//遍历元素
System.out.println("--------------普通for循环------");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
System.out.println("使用扩展出来的listIterator()方法遍历");
ListIterator listIterator=list.listIterator();
/*System.out.println("后面有元素吗?"+listIterator.hasNext());
System.out.println("前面有元素吗?"+listIterator.hasPrevious());
listIterator.next();//取出一个元素
System.out.println("后面有元素吗?"+listIterator.hasNext());
System.out.println("前面有元素吗?"+listIterator.hasPrevious());*/
System.out.println("正向遍历之前"+listIterator.hasNext()+"\t"+listIterator.hasPrevious());
while(listIterator.hasNext()){
System.out.println(listIterator.next());
}
System.out.println();
System.out.println("正向遍历之后:"+listIterator.hasNext()+"\t"+listIterator.hasPrevious());
System.out.println("逆向遍历:");
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}
System.out.println("逆向遍历之后:"+listIterator.hasNext()+"\t"+listIterator.hasPrevious());
}
}
泛型:是创建集合对象时对集合中存储的元素的数据类型进行限制
泛型符号:<数据类型>
泛型起作用的时间点:javac编译之前。
泛型的分类
(1)泛型接口
public interface Collection<E>{ //E代表一种数据类型,这个类型什么时候才能知道
}
//在创建接口的实现类对象时,才能知道,在如下代码中,E所代表的数据类型是Integer
Collection<Integer> coll=new ArrayList<Integer>();
(2)泛型类
public class ArrayList<E>{ //E的数据类型什么时候知道,创建ArrayList对象时知道
}
ArrayList<String> al=new ArrayList<String>();
(3)泛型方法
public boolean add(E e) {}
//E也代表一种数据类型 ,这个E的数据类型与ArrayList<E> 完全相同的,所以E的类型是在创建ArrayList的对象时确定
可变参数的泛型方法 :
(1)可变参数是JDK1.5
(2)泛型也是JDK1.5
public class Client <T>{ //泛型类
public void show(T t){ //泛型方法
System.out.println(t);
}
public <Q> void fun(Q q){ //Q的数据类型是在调用该方法时决定
System.out.println("q="+q);
}
public <P>void method(P...p){
//加强for循环
for(P i:p){
System.out.println(i);
}
}
}
import java.util.Date;
public class Test {
public static void main(String[] args) {
Client<String> client=new Client<String>();//T的类型是String
client.show("hello");
//泛型方法,数据类型是在调用该方法时明确的,解决了同一个类中参数个数相同,类型不同的方法重载问题
client.fun("hello");
client.fun(123);
client.fun(new Date());
//可变参数的泛型方法,解决了数据类型不同,个数不同的方法重载问题
client.method("hello");
client.method("world1","world2","world3");
client.method(123);
client.method(8.7,9.8,7.6,9.9);
//可变参数实际上就是一个数组
Client<Integer> client2=new Client<Integer>();//T的类型时Integer
client2.show(123);
}
}