1. 集合与数组
1.1 数组的缺陷
1. 长度开始时必须指定,而且一旦指定,不能更改
2. 保存的必须为同一类型的元素
3. 使用数组进行增加/删除元素的示意代码-比较麻烦
1.2 集合
1. 可以动态保存任意多个对象,使用比较方便
2. 提供了一系列方便的操作对象的方法:add、remove、set、get等
3. 使用集合添加,删除新元素的示意代码-简洁明了
2. 集合的框架体系
根据不同的数据结构,比如数组,线性,链表结构等开发出不同的类。
这些类称为java中集合框架。
Java 的集合类很多,主要分为两大类,如图 :
2.1 Vector类
public class Vector<E> ---<E>理解为Object
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
Vector类实现了可扩展的对象数组。 像数组一样,它包含可以使用下标访问的元素。 但是, Vector的大小可以根据需要增长或缩小,以适应在创建Vector之后添加和删除项目。
-----------------我们如果想使用Vector类,那么必须创建Vector类对象------------
Vector()
构造一个空向量,使其内部数据数组的大小为 10 ,标准容量增量为零。Vector(int initialCapacity)
构造具有指定初始容量并且其容量增量等于零的空向量。
import java.util.Vector;
public class Test02 {
public static void main(String[] args) {
//1.创建一个Vector对象
// Vector v=new Vector();//默认容量为10
Vector v=new Vector(3);
//2. 添加元素
v.add("张三");
v.add("李四");
v.add(1,"王五");//插入
v.add("张三");//插入---允许元素重复
//3.获取元素的个数
System.out.println("元素的个数:"+v.size());
//4. 获取指定位置的元素
System.out.println("获取第一个位置的元素:"+v.get(1));
//5.判断某个元素是否存在.
System.out.println("张三2是否存在:"+v.contains("张三2"));
//6.查找元素第一次在Vector中出现的位置。
System.out.println("张三2第一次出现的位置:"+v.indexOf("张三2"));
System.out.println("修改前:"+v);
//7.修改指定位置元素
v.set(1,"赵六");
System.out.println("修改后:"+v);
//8.删除
v.remove(1);//删除指定位置的元素
System.out.println("删除后:"+v);
//9.清空
v.clear();
System.out.println("清空后:"+v);
}
}
Vector集合的遍历
Vector v=new Vector(3);
//2. 添加元素
v.add("张三");
v.add("");
v.add(1,"王五");//插入
v.add("张三");//插入---允许元素重复
//for循环
for(int i=0;i<v.size();i++){
System.out.println(v.get(i));
}
//增强for循环遍历
System.out.println("=============增强for循环遍历=============");
for(Object o:v){
System.out.println(o);
}
//迭代器遍历
System.out.println("===============迭代器遍历===================");
Iterator iterator = v.iterator();//获取v的迭代器对象
while (iterator.hasNext()){ //判断是否还有元素
Object o = iterator.next();//获取元素并移动指针
System.out.println(o);
}
2.2 ArrayList集合
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
可调整大小的数组的实现List接口。 实现所有可选列表操作,并允许所有元素,包括null 。 除了实现List 接口之外,该类还提供了一些方法来操纵内部使用的存储列表的数组的大小。 (这个类是大致相当于Vector,不同之处在于它是不同步的)。Vector和ArrayList的区别?
Vector:底层使用的还是数组,同步操作,线程安全的。效率慢。
ArrayList:底层使用还是数组,非同步操作,线程不安全。效率高。---【一般使用】------------------如果我们想使用ArrayList必须创建该类对象-------------------
ArrayList()
构造一个初始容量为十的空列表。
ArrayList(int initialCapacity)
构造具有指定初始容量的空列表。
public static void main(String[] args) {
ArrayList list=new ArrayList();//创建一个集合对象
ArrayList list2=new ArrayList();//创建一个集合对象
list2.add("java01");
list2.add("java02");
list2.add("java03");
list2.add("java06");
list2.add("java02");
list.addAll(list2);//把list2集合中的内容放到list集合中
System.out.println("集合中的内容:"+list);
Object clone = list.clone(); //克隆方法
System.out.println("集合是否为空:"+list.isEmpty());
List list1 = list.subList(1, 3);//截取集合
System.out.println(list1);
Object[] objects = list.toArray();
System.out.println(Arrays.toString(objects));
}
ArrayList底层源码
1. 构造函数
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//Object[] elementData;
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
2.add方法。
public boolean add(Object e) { //E:理解为Object
ensureCapacityInternal(size + 1); // 扩容数组
elementData[size++] = e;//把元素赋值给指定下的位置
return true;
}
private void ensureExplicitCapacity(int minCapacity) {//元素的个数
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //求原来数组的长度
int newCapacity = oldCapacity + (oldCapacity >> 1);// >>1表示0.5倍--1.5
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) //1555555555555555
newCapacity = hugeCapacity(minCapacity);
// 数组的赋值和扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}
3.size方法.
public int size() {
return size;
}
4.get方法 get(2)
public E get(int index) {
rangeCheck(index); //检查下标是否合法
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
5.remove(1)删除方法:
public E remove(int index) {
rangeCheck(index); //检查下标是否合法
modCount++;
E oldValue = elementData(index); //获取该位置上的元素
//5-2-1
int numMoved = size - index - 1; //size元素的个数 index删除的位置
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
------------------------------------------------------------------------
ArrayList查询效率高,删除操作设计到位移时比较慢。
2.3 LinkedList集合
LinkedList的使用
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
双向链表实现了List和Deque接口。 实现所有可选列表操作,并允许重复元素(包括null )。
LinkedList()
构造一个空列表。
无需指定初始化容器,因为他底层不是用的数组结构。
import java.util.Iterator;
import java.util.LinkedList;
public class Test01 {
public static void main(String[] args) {
LinkedList list=new LinkedList();
//添加元素--->add和addLast是两个人写的。
list.add("java01");
list.add("java02");
list.addFirst("java03");
list.addLast("java04");
//修改
list.set(1,"java05");
System.out.println(list);
//长度
System.out.println(list.size());
//获取指定位置的元素
System.out.println(list.get(2));
//截取
System.out.println(list.subList(1, 3));
//判断是否包含某元素
System.out.println(list.contains("java05"));
//第一次出现的位置
System.out.println(list.indexOf("java05"));
//遍历
System.out.println("==================================");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("==================================");
for (Object o:list){
System.out.println(o);
}
System.out.println("==================================");
Iterator iterator=list.iterator();
while (iterator.hasNext()){
Object o=iterator.next();
System.out.println(o);
}
System.out.println("==================================");
list.forEach(item->System.out.println(item));
//删除
}
}
LinkedList底层实现原理
构造方法:
transient int size = 0;
transient Node<E> first=null;
transient Node<E> last=null;
public LinkedList() {
}
add()添加方法
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);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
private static class Node<E> {
E item; //表示当前添加的元素
Node<E> next; //表示下一个node节点
Node<E> prev; //表示上一个node接口
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
get(2): 获取指定元素. ---要么从链表的头 要么从链表的尾 直到索引得到位置。
public E get(int index) {
checkElementIndex(index);//检查下标是否合法
return node(index).item;
}
//index=1 size=5
Node<E> node(int index) {
if (index < (size >> 1)) { //5/2=
Node<E> x = first; //
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--){
x = x.prev;
}
return x;
}
}
remove(2):移除元素
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index)); //node(index):找到被移除的节点对象
}
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next; //java04节点
final Node<E> prev = x.prev; //java02节点
if (prev == null) {
first = next;
} else {
prev.next = next; //java02指向java04节点
x.prev = null; //java03节点的上一个置空
}
if (next == null) {
last = prev;
} else {
next.prev = prev; //java04的指向java02
x.next = null; //java03节点的下一个置空
}
x.item = null; //item=null;
size--; //数量减一
modCount++;
return element; //java03内容
}
2.4 HasSet
实现了Set,该类不允许重复,而且无序 且没有下标。底层使用hash算法实现。 HashSet元素是否重复根据哈希值以及equals方法判断。
import java.util.HashSet;
import java.util.Iterator;
public class Test01 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
//添加元素
set.add("java01");
set.add("java06");
set.add("java02");
set.add("java08");
set.add("java06");
set.add(null);
set.add(null);
set.add(null);
System.out.println(set); //set不允许重复而且无序,允许存放null.
//元素的个数
System.out.println(set.size());
//遍历--增强
for (String s : set) {
System.out.println(s);
}
System.out.println("==========================");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
System.out.println(s);
}
System.out.println("==========================");
set.forEach(item->System.out.println(item));//jdk1.8
//删除
boolean b = set.remove("java06");
System.out.println(set);
//清空
// set.clear();
//包含某个元素
System.out.println(set.contains("java02"));
}
}
import java.util.HashSet;
import java.util.Objects;
public class Test02 {
public static void main(String[] args) {
People p1 = new People("jack", 23);
People p2 = new People("tom", 33);
People p4 = new People("jack", 33);
People p3 = new People("smith", 23);
HashSet<People> set=new HashSet<>();
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4); //判断重复的依据: hashCode()和equals()比较的地址. 先比较hashCode(),如果hashcode值相同再比较equals()。 如果hashcode值不同则不会调用equals();
System.out.println("集合元素的个数:"+set.size());
System.out.println(set);
}
}
class People{
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
People people = (People) o;
return this.getAge() == people.getAge() && Objects.equals(getName(), people.getName());
}
@Override
public int hashCode() { //"aaa"--->整数
return Objects.hash(getName(), getAge()); //根据名称和年龄计算hash值。
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
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;
}
}
如果集合HahSet中添加的类型为自定义类对象。那么该类建议重写equals和hashcode方法。
2.5 HashMap
它底层也是使用了Hash表。 存放的元素key---value键值对元素。而且它的key不允许重复。但是value允许重复。 而且HashMap运行key和value为null;
基于哈希表的实现的Map接口。 此实现提供了所有可选的地图操作,并允许null的值和null键。
import java.util.HashMap;
import java.util.Set;
public class Test04 {
public static void main(String[] args) {
HashMap map=new HashMap();//map的键是唯一的,如果添加相同的键,后面的值会覆盖前面的值。
//添加元素
map.put("name","郭宇轩");//添加元素到map对象中
map.put("age",16);
map.put("sex","男");
map.put("name","刘力元");
System.out.println(map);
//获取元素--通过key获取元素的value值
System.out.println(map.get("name"));
//元素的个数
System.out.println("元素的个数:"+map.size());
//删除元素
map.remove("sex");
System.out.println(map);
//获取map中所有的key
Set keys = map.keySet();
System.out.println("所有的key:"+keys);
//遍历所有key
for(Object k:keys){
System.out.println(k+"---------------->"+map.get(k));
}
//判断是否包含某个元素
System.out.println(map.containsKey("name"));
map.clear();//clean
}
}
标签:set,Java,Day07,System,println,add,集合,public,out From: https://blog.csdn.net/Flipped_275/article/details/144407346