1.容器的简介:
上图这些都是接口:
可以先看一下Collection的源码;
Collection定义了存取一组对象的方法:List和Set为他的子接口;
List 是有序可重复的
Set是无顺序不可重复
Map是键(keys)值(value)映射对(他的Key是不可以重复的 重复就覆盖了);
操作的时候 是对他们的地址进行操作;
容器null和isEmpty的区别:将容器比作装苹果的篮子,那么isEmpty就是只有一个篮子而没有苹果,null是指连篮子这个对象都没有;
定义一个Object[] 数组那就以为只什么都可以往里放(结合拆箱和装箱的知识);
Remove指的是移除而不是删除(只是把一个对象从篮子里移出去了 而不是把这个对象本身删除了);
int indexOf(Object o);指的是看看包不包含这个元素如果包含就返回索引值,否则返回-1;还有一个lastIndexOf()就是倒着数,和String中的功能基本一致;
List他的实现类中有两个重要的:ArraylLst和LinkedList;还有一个可能遇见的Vector
size指的是元素有多少个,肯定不是数组的长度,数组肯定要大于等于他才能装的下他;
package testCollection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 测试关于Collection的一些子接口和他们的实现类
* @author Wang
*
*/
public class testCollection1 {
public static void main(String[] args) {
List list = new ArrayList();//一般都是用这样的写法 写一个接口然后new他的子实现类 方便换后面的实现类
//ArrayList:底层实现时数组,线程不安全,效率高。所以,查询快。修改、插入、删除慢。
//LinkedList:底层实现是链表,线程不安全,效率高。所以,查询慢。修改、插入、删除快。
//Vector:线程安全的,效率低。 他的底层实现也是数组
list.add("aaa");//往容器里面添加东西 一般都是用Object[]数组来实现容器
list.add("bbb");
list.add(new Date());
Dog a = new Dog("哈士奇");
list.add(a.GetName());
list.add(1234); //这不是类但是会用到包装类的:自动装箱! 这里相当于Integer i = new Integer(123);然后吧i加进去
list.remove(new String("aaa"));
System.out.println(list.size());//输出list里面有多少东西
for(int i=0;i<list.size();i++){//遍历输出 list.get()方法
System.out.println(list.get(i));
}
list.set(3, new String("3333"));//用指定的元素替换此列表中指定位置的元素。
list.add(4, new String("3333"));//在此列表中的指定位置插入指定的元素。
System.out.println(list.isEmpty());
//list.remove(new Dog()); //移除的对象和前面添加的那个对象确实并不是一个(但他的底层使用equals方法) 这里牵涉到了hashcode和equals
System.out.println(list.size());
List list2 = new ArrayList();
list2.add("bbb");
list2.add("ccc");
list.add(list2);
//跟顺序的操作
String str = (String) list.get(0);
System.out.println(str);
list.set(1, "ababa");
list.remove(0);
}
}
class Dog{
String name;
Dog(){}
public Dog(String name) {
this.name = name;
}
public String GetName() {
return name;
}
}
2.equal与==的详解:
String中的equal重写object的equal,前者指的是比较
-
将此字符串与指定对象进行比较。 其结果是
true
当且仅当该参数不是null
并且是String
对象,表示相同的字符序列作为该对象。public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}//就是先比较地址在比较内容 这是他的源码 与API的介绍; -
==指的是比较地址 即是比较是不是一个对象
而Object中的equals是这样的
public boolean equals(Object obj) {
return (this == obj);}//也就相当于只是一个== 就是比较是否是一个地址(对象)
小结:每个类的equals都可能不一样具体要看他们的源码;
ArrayList数组查找的时候是最快的,修改,插入和删除慢,LinkedList底层实现是链表反之;
Vector:他的底层实现也是数组线程安全的,效率低,前面那两个是线程不安全,效率高;想起了StringBuilder和StringBuffer;
3.自己写的MyArrayList02;
package testCollection;
/**
* 再次写一个ArrayList 上次是根据StringBuilder来写 这次就根据ArrayList来写
* @author Wang
* 目标:更加熟练的掌握ArrayList
*/
public class MyArrayList02 {
private Object[] elementData;
private int size;//这个size代表的是链表里面内容的个数
public MyArrayList02() {//无参构造函数
this(10);//这句会自动调用有参构造函数 也就是无参构造函数的默认空间是10 注意一个数组a[10]他表示是10个空间他的索引是0到9而不是0到10
}
public MyArrayList02(int initArea) {//有参构造函数
elementData = new Object[initArea];
}
private void RangeCheck(int index) {//检查索引是否越界
if(index<0||index>=size) {
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void ensureStorage() {//数组的扩容
if(size == elementData.length) {
Object[] newArray = new Object[size*2+1];
System.arraycopy(elementData, 0, newArray, 0, elementData.length);//将elementData中的元素(第一个参数从0开始)复制到newArray从newArray的0位置开始(第二个参数)复制elementData.length个
elementData = newArray;
}
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
public int indexOf(Object o) {
if(o == null) {
for(int i=0; i<size; i++) {
if(elementData[i] == null) {
return i;
}
}
}else {
for(int i=0;i<size;i++) {
if(elementData[i].equals(o)) {
return i;
}
}
}
return -1;
}
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
public Object get(int index) {
RangeCheck(index);
return elementData[index];
}
public void add(Object o) {
ensureStorage();
elementData[size++] = o;
}
public void remove(int index) {//移除指定位置的元素
RangeCheck(index);
int numMoved = size - index -1;
if(numMoved>0) {
System.arraycopy(elementData, index+1, elementData,index , numMoved);
}
elementData[--size] = null;
}
public void remove(Object o) {//删除对象o
if(o == null) {
System.out.println("你想要删除的对象是空,这是一个无用操作");
}
for(int i = 0;i<size;i++) {
get(i).equals(o);
remove(i);//调用了删除指定位置元素的方法;
}
}
public Object set(int index,Object o) {//将指定位置的元素设置为o 返回你修改的那个元素本来是什么
RangeCheck(index);
Object old = elementData[index];
elementData[index] = o;
return old;
}
public static void main(String[] args) {
MyArrayList02 a = new MyArrayList02(3); //这里是直接顶一个容器了 不要写成这个样子 MyArrayList02[] a = new MyArrayList02();
a.add("aaa");
a.add("bbb");
a.add(333);
a.add(new Dog());
System.out.println(a.size());
a.remove(2);
System.out.println(a.get(2));
}
}
注意:
1.注意一个数组a[10]他表示是10个空间他的索引是0到9而不是0到10;
2.注意MyArrayList02中的移除操作以后数组的索引的变化;