目录
ArrayList集合初始化容量是10,ArrayList底层是Object数组,扩容是原来的1.5倍,建议给个预估计的初始化容量,扩容底层调用了数组扩容
此方法。数组优点:检索效率高。缺点:增加元素效率较低,但是给末尾添加元素效率无影响。
List接口下的实现类
ArrayList
package edu.tjdz.javaSE.collection.com.tjdz.javaSE.collection.List;
import java.util.ArrayList;
import java.util.List;
/*
ArrayList集合:
1、默认初始化容量10。(底层先创建了一个初始化容量为0的数组,当添加第一个元素的时候,初始化容量变为10)
2、集合底层是一个Object数组。
3、构造方法:
new ArrayList();
new ArrayList(20);
4、ArrayList集合的扩容:
原容量的1.5倍。
ArrayList集合底层是数组,如何优化?
竟可能少的扩容。因为数组扩容效率比较低,建议在使用
ArrayList集合的时候估计元素的个数,给定一个初始化值。
5、数组优点:
检索效率比较高。(每个元素占用空间大小相同,内存地址是连续的,知道元素的内存地址
,然后知道元素的下标,通过数学表达式,检索效率最高[通过内存地址定位]。)
6、数组缺点:
随机增删元素效率比较低
另外数组无法存储大数据量。(很难找到一大块连续的内存空间)
7、向数组末尾添加元素,效率还是很高的,不受影响。
8、面试官经常问到的一个问题?
这么多集合,你用那个集合最多?
答:ArrayList集合。
因为往ArrayList数组末尾添加元素时,效率很高,不受影响。
另外,检索元素操作比较多,这个集合检索效率高。
9、ArrayList集合是非线程安全的。(不是线程安全集合)
*/
public class ArrayListTesrt01 {
public static void main(String[] args) {
//默认初始化容量为10
//数组的长度为10
List list1 = new ArrayList();
//集合size()获取当前集合中元素的个数
System.out.println(list1.size()); //0
//指定初始化
//数组的长度为20
List list2 = new ArrayList(20);
//集合size()方法是获取当前集合元素的个数,不是集合的容量
System.out.println(list2.size());
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
list1.add(6);
list1.add(7);
list1.add(8);
list1.add(9);
list1.add(10);
System.out.println(list1.size());
//再加一个元素
list1.add(11);
System.out.println(list1.size());
}
}
package com.tjdz.javaSE.collection.com.tjdz.javaSE.collection.List;
import java.util.*;
/*
集合ArrayList的构造方法
ArrayList(Collection<? extends E> c)
*/
public class ArrayListTest02 {
public static void main(String[] args) {
//默认初始化容量10
List myList1 = new ArrayList();
// 指定初始化容量100
List myList2 = new ArrayList(100);
//创建一个HashSet集合
Collection c = new HashSet();
c.add(100);
c.add(200);
c.add(900);
c.add(50);
System.out.println("-----------------------------------");
// 通过这个构造方法就可以将HashSet集合转换成List集合
List myList3 = new ArrayList(c);
//迭代
Iterator it = c.iterator();
while(it.hasNext()){
Object obj = it.next();
System.out.println(obj);
}
System.out.println("=======================================");
//遍历
for(int i=0;i<myList3.size();i++){
System.out.println(myList3.get(i));
}
}
}
package com.tjdz.javaSE.collection.com.tjdz.javaSE.collection.List;
/*
位运算符 >>
*/
public class BinaryTest {
public static void main(String[] args) {
// 5
// >> 1 二进制右移一位
// >> 2 二进制右移两位
// 10的二进制位是:00001010 【10】
// 10的二进制位右移一位是:00000101 【5】
System.out.println(10 >> 1); //右移一位就是除以2
//二进制位左移一位
// 10的二进制位是:00001010 【10】
// 10的二进制位左移1位:00010100 【20】
System.out.println(10 << 1); //20
}
}
单链表数据结构
package edu.tjdz.javaSE.collection.danlianbiao;
/*
单链表中的节点:
节点是单链表的基本单元。
每一个节点都有两个属性:
一个属性:是存储的数据。
另一个属性:是下一个节点的内存地址。
*/
public class Node {
// 存储的数据
Object element;
//下一个节点的内存地址
Node next;
public Node(){
}
public Node(Object element,Node next){
this.element=element;
this.next=next;
}
}
package com.tjdz.javaSE.collection.danlianbiao;
/*
链表类
*/
public class Link<E> {
//头节点
Node header = null;
int size = 0;
public int Size(){
return size;
}
//向链表中添加元素的方法
public void add(E data){
// 创建一个新的节点对象
// 让之前单链表的末尾节点next指向新的节点对象
// 有可能这个元素是第一个,也有可能是第二个,也有可能是第三个。
if (header == null){
//说明还没有节点
//new一个节点对象,作为头节点对象
//这个时候的头节点即是一个头节点,也是一个尾节点
header = new Node(data,null);
}else{
// 说明头不是空
// 头节点已经存在了
// 找出当前末尾节点,让当前末尾节点的next是新节点。
Node currentLastNode = findLast(header);
currentLastNode.next = new Node(data,null);
}
size++;
}
/**
* 专门用来查找末尾节点的方法
* @return header
*/
private Node findLast(Node node){
if(node.next == null){
//如果一个节点的next是null
//说明这个节点就是末尾节点
return node;
}
return findLast(node.next);
}
//删除链表中某个数据逇方法
public void remove(Object obj){
}
//修改链表中某个数据的方法
public void modify(Object newObj){
}
//查找链表中某个元素的方法
public int find(Object obj){
return 1;
}
public static void main(String[] args) {
Link<String> link = new Link<>();
link.add("1536");
//类型不匹配
//link.add(123);
}
}
package com.tjdz.javaSE.collection.danlianbiao;
public class Test {
public static void main(String[] args) {
//创建了一个集合
Link link = new Link();
//添加元素
link.add(100);
link.add(200);
link.add(300);
//获取元素个数
System.out.println(link.size);
}
}
实现类Linkednlei
package edu.tjdz.javaSE.collection.danlianbiao;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/*
链表的优点:
由于链表上的元素在空间存储上内存地址连续。
所以随机增删元素的时候不会有大量的位移,因为增删效率较高。
在以后的开发中,如果遇到随机增删元素的业务比较多时,建议
使用LinkedList.
链表的缺点:
不能通过数学表达式计算被查找的元素的内存地址,每一次查找都是从头
节点开始遍历,知道找到为止。所有LinkedList集合检索/查找的效率
较低。
ArrayList:把检索效率发到最高。
LinkedList:把随机增删元素发挥到极致。
加元素都是往末尾添加,所以ArrayList用的比LinkedList多一些。
*/
public class LinkedListTest01 {
public static void main(String[] args) {
//LinkedList几层也是有下标的
// 注意:ArrayList之所以检索效率比较高,不是单纯因为由下标的原因,是因为底层数组发挥的作用。
//LinkedList节点照样有下标,但是检索/查找某个元素的时候比较低,因为只能从头节点一个一个遍历。
List list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
for(int i =0;i<list.size();i++){
System.out.println(list.get(i));
}
// LinkedList集合有初始化容量吗?没有。
// 最初这个链表中没有任何元素。first和last引用都是null。
// 不管是LinkedList还是ArrayList,以后写代码时都不需要关心是哪个集合。
// 因为我们要面向接口编程,调用方法都是接口中的方法。
//List list2 = new ArrayList(); //这样写表示底层用了数组
List list2 = new LinkedList(); //这样写表示底层用了双向链表。
// 以下这些方法都是面向接口编程
list2.add("123");
list2.add("456");
list2.add("789");
for(int i=0;i<list2.size();i++){
System.out.println(list2.get(i));
}
}
}
实现类Vector
package edu.tjdz.javaSE.collection.Vector;
import java.util.*;
/*
Vector:
1、底层也是一个数组。
2、初始化容量:10
3、怎么扩容?
扩容之后是元容量的2倍。
10--->20--->40--->80
4、ArrayList集合扩容特点?
原容量的1.5倍
5、怎么将一个线程安全的ArrayList集合转换成线程安全的呢?
使用集合工具类:
java.util.Collections;
java.util.Collection;是集合接口。
java.util.Collections;是集合工具类。
*/
public class VectorTest {
public static void main(String[] args) {
//创建Vector集合
Vector vector = new Vector();
//添加元素
//默认容量10个
vector.add(1);
vector.add(2);
vector.add(3);
vector.add(4);
vector.add(5);
vector.add(6);
vector.add(7);
vector.add(8);
vector.add(9);
vector.add(10);
//满了之后扩容
vector.add(11);
Iterator it = vector.iterator();
while(it.hasNext()){
Object obj = it.next();
if(obj instanceof Integer){
System.out.println("Integer类型!");
}
System.out.println(obj);
}
//以后可能会用
List myList = new ArrayList(); //非线程安全的
//变成线程安全的
Collections.synchronizedList(myList); //这里没办法看效果
myList.add("111");
myList.add("222");
myList.add("333");
}
}
collection下所有子类的通用方法
/* 关于java.util.Collection接口中的方法。 1、Collection中能存放什么元素? 没有使用“泛型”之前,Collection中可以存放Object的所有子类型。 使用了“泛型”之后,Collection中只能存储某个具体类型。 集合后期会讲到“泛型”语法。目前先不用管。Collection中什么都 能存,只要是Object的子类就行。(集合中不能直接存储基本数据类型, 也不能存java对象,只能存储java对象的内存地址) 2、Collection中的常用方法 boolean add(Object e) 往集合中添加元素 int size() 获取集合中元素的个数,从1开始,以1递增 void clear() 清空集合 boolean contains(Object o) 判断集合中是否包含这个o元素,包含返回true,不包含返回false boolean remove(Object o) 删除集合中的某个元素 boolean isEmpty() 判断集合是否为空 Object[] toArray() 调用这个方法可以将集合转换成数组【作为了解,使用不多】 */关于collection下的常用方法
/* 测试List接口中的常用方法 1、List集合存储元素特点:有序可重复 有序:List集合中元素由下标。 从0开始,以1递增。 可重复:存储一个1,还可以在存储一个1. 2、List即是Collection接口中的子接口,那么肯定List接口有自己“特色”的方法: 以下只列出List特有的常用的方法 void add(int index, E element) 在列表的指定位置添加元素(第一个参数是下标) Object get(int index) 根据下标获取元素(元素的下标,从0开始,以1递增) int indexOf(Object o) //获取指定对象第一次出现的索引 int lastIndexOf(Object o) //获取指定对象最后一次出现的索引 Object remove(int index) //删除指定下标位置的元素 Object set(int index, Object element) //修改指定位置元素(元素下标,修改的值) */SUN下的add方法
ArrayList集合初始化容量是10,ArrayList底层是Object数组,扩容是原来的1.5倍,建议给个预估计的初始化容量,扩容底层调用了数组扩容
System.arraycopy(elementData, index, elementData, index + 1, size - index);
此方法。数组优点:检索效率高。缺点:增加元素效率较低,但是给末尾添加元素效率无影响。
关于集合的继承图
Collection集合
Map集合继承图