一、Java容器的整体结构
二、List用法
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 测试List接口的常用方法
*/
public class TestList {
public static void main(String[] args) {
test3();
}
/**
* 测试List的常用方法
*/
public static void test1(){
List list=new ArrayList();
System.out.println(list.isEmpty());
list.add("张三");
System.out.println(list);
System.out.println(list.isEmpty());
list.add("李四");
list.add("王五");
System.out.println(list);
System.out.println("List的大小:"+list.size());
System.out.println("List是否包含:"+list.contains("李四"));
list.remove("李四");
System.out.println(list);
Object[] objs=list.toArray();
System.out.println("转换成Object数组:"+ Arrays.toString(objs));
list.clear();
System.out.println(list);
}
/**
* 测试和索引操作的相关方法
*/
public static void test2(){
//List存储的是:有序,可重复
List list=new ArrayList();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
System.out.println(list);
list.add(2,"高");
System.out.println(list);
list.remove(2);
System.out.println(list);
list.set(2,"喝杯水");
System.out.println(list);
System.out.println(list.get(2));
list.add("A");
System.out.println(list);
System.out.println(list.indexOf("A"));
System.out.println(list.lastIndexOf("A"));
}
/**
* 测试两个容器之间元素处理
*/
public static void test3(){
List list=new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("马汉");
List list1=new ArrayList();
list1.add("张龙");
list1.add("赵虎");
list1.add("马汉");
System.out.println(list.containsAll(list1));
list.addAll(list1);
System.out.println(list);
// list.removeAll(list1);
// System.out.println(list);
System.out.println(list);
System.out.println(list1);
list.retainAll(list1);
System.out.println(list);
}
}
三、Set用法
/**
* 测试Set
* Set 无序,不可重复
*/
public class TestSet {
public static void main(String[] args) {
test2();
}
public static void test1(){
Set set=new HashSet();
set.add("hello");
set.add("world");
set.add("hello"); //相同的元素不再被加入
System.out.println(set);
}
//Set中不可重复的核心:equals()方法
public static void test2(){
Emp e1=new Emp(1001,"张三");
Emp e2=new Emp(1002,"李四");
Emp e3=new Emp(1001,"王五");
Set s=new HashSet();
s.add(e1);
s.add(e2);
s.add(e3);
System.out.println(s);
}
}
class Emp{
private int id;
private String ename;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Emp emp = (Emp) o;
return id == emp.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", ename='" + ename + '\'' +
'}';
}
public Emp(int id, String ename) {
this.id = id;
this.ename = ename;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
}
四、Map用法
/**
* 测试Map的使用方法
*/
public class TestMap {
public static void main(String[] args) {
test4();
}
//Map的常见用法
public static void test1() {
Map m1 = new HashMap();
m1.put(1, "one");
m1.put(2, "two");
m1.put(3, "three");
System.out.println(m1);
//如果键重复,就替换掉旧的键值对
m1.put(2, "二");
Object o = m1.get(2);
System.out.println(o);
System.out.println(m1);
System.out.println(m1.containsKey(4));
System.out.println(m1.containsValue("three"));
m1.remove(2);
System.out.println(m1);
Map m2 = new HashMap();
m2.put("yi", "111");
m2.put("er", "222");
m2.put(3, "333");
m1.putAll(m2);
System.out.println(m1);
}
//泛型的简单用法
public static void test2() {
List<String> list = new ArrayList<String>();
list.add("name");
String str = list.get(0);
System.out.println(str);
Set<Integer> set = new HashSet<>();
set.add(123);
System.out.println(set);
Map<Integer, String> m2 = new HashMap<>();
m2.put(1, "一");
m2.put(2, "二");
m2.put(3, "三");
}
/**
* 容器的遍历
* 遍历List、Set
*/
public static void test3() {
List<String> s = new ArrayList<>();
// Set<String> s=new HashSet<>();
s.add("aa");
s.add("bb");
s.add("cc");
//通过索引遍历list,只适用于List。
for (int i = 0; i < s.size(); i++) {
String temp = s.get(i);
System.out.println(temp);
}
//通过增强for循环遍历list,适用于List、Set
for (String temp : s) {
System.out.println(temp);
}
//使用Iterator(迭代)对象遍历,适用于List、Set
for (Iterator iter = s.iterator(); iter.hasNext(); ) {
String temp = (String) iter.next();
System.out.println(temp);
}
}
/**
* 容器的遍历
* 遍历Map(遍历key和value)
*/
public static void test4() {
Map<String, String> map = new HashMap<>();
map.put("one", "一");
map.put("two", "二");
map.put("three", "三");
Set<String> keys = map.keySet();
//通过增强for循环遍历Set,适用于List、Set
for (String temp : keys) {
System.out.println(temp);
}
//使用Iterator(迭代)对象遍历,适用于List、Set
for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
String temp = (String) iter.next();
System.out.println(temp);
}
//遍历健值
for (String temp : keys) {
System.out.println(map.get(temp));
}
Collection<String> values = map.values();
for (String temp : values) {
System.out.println(temp);
}
//使用EntrySet,遍历Key和value
Set<Map.Entry<String,String>> entrySet=map.entrySet();
for(Map.Entry e:entrySet){
System.out.println(e.getKey()+"====="+e.getValue());
}
}
}
五、存取二维表格信息
package com.myproject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 使用容器的不同方式,存储表格的信息
*/
public class StoreTable {
public static void main(String[] args) {
test2();
}
//使用Map方式来存储
public static void test1(){
Map<String,Object> m1=new HashMap<>();
m1.put("id",1001);
m1.put("title","我爱开发");
m1.put("createDate","2021-8-10");
m1.put("length",300);
Map<String,Object> m2=new HashMap<>();
m2.put("id",1002);
m2.put("title","我爱数据");
m2.put("createDate","2021-9-10");
m2.put("length",400);
Map<String,Object> m3=new HashMap<>();
m3.put("id",1003);
m3.put("title","我爱编程");
m3.put("createDate","2021-9-12");
m3.put("length",500);
//存储了整个表格的信息
List<Map<String,Object>> list=new ArrayList<>();
list.add(m1);
list.add(m2);
list.add(m3);
System.out.println("id\t\ttitle\t\tcreateDate\tlength");
for(int i=0;i<list.size();i++){
Map<String,Object> temp=list.get(i);
System.out.println(
temp.get("id")+"\t"
+temp.get("title")+"\t\t"
+temp.get("createDate")+"\t"
+temp.get("length")
);
}
}
//使用List+Javabean的方式来存储
public static void test2(){
VideoInfo v1=new VideoInfo(1001,"我爱开发","2021-8-10",300);
VideoInfo v2=new VideoInfo(1002,"我爱数据","2021-9-10",400);
VideoInfo v3=new VideoInfo(1003,"我爱编程","2021-9-12",380);
List<VideoInfo> list=new ArrayList<>();
list.add(v1);
list.add(v2);
list.add(v3);
// for(int i=0;i<list.size();i++){
// System.out.println(list);
// }
System.out.println("id\t\ttitle\tcreateDate\tlength");
for(VideoInfo temp:list){
System.out.println(temp);
}
}
}
class VideoInfo{
private int id;
private String title;
private String createDate;
private int length;
public VideoInfo(int id, String title, String createDate, int length) {
this.id = id;
this.title = title;
this.createDate = createDate;
this.length = length;
}
@Override
public String toString() {
return
getId() +"\t"
+ getTitle() + "\t"
+ getCreateDate() + "\t"
+ getLength();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
public String getLength() {
if(this.length<60){
return this.length+"秒";
}else if(this.length<3600){
int minutes=this.length/60;
int seconds=this.length%60;
return minutes+"分"+seconds+"秒";
}else{
int hours=this.length/3600;
int minutes=(this.length/3600)/60;
int seconds=(this.length/3600)%60;
return hours+"时"+minutes+"分"+seconds+"秒";
}
}
public void setLength(int length) {
this.length = length;
}
}
六、泛型详解
/**
* 测试泛型的基本用法
*/
public class TestGeneric {
public static void main(String[] args) {
}
public static void test1(){
Generic1<Integer> g1=new Generic1<>();
g1.aa(22);
g1.bb(333);
Generic1<String> g2=new Generic1<>();
g2.aa("111");
g2.bb("aaa");
}
}
//定义一个简单的泛型类
class Generic1<T>{
public T aa(T obj){
System.out.println(obj);
return obj;
}
public <N> void bb(N obj){
System.out.println(obj);
}
}
interface MyList<E>{
int size();
boolean isEmpty();
void add(E e);
E get(int index);
}
class MyArrayList<E> implements MyList<E>{
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public void add(E e) {
}
@Override
public E get(int index) {
return null;
}
}
package com.myproject;
import java.util.ArrayList;
import java.util.List;
/**
* 通配符?和上下限定
*/
public class TestGeneric2 {
public static void main(String[] args) {
List<Aniaml> list1=new ArrayList<>();
List<Dog> list2=new ArrayList<>();
List<TaiDi> list3=new ArrayList<>();
// test1(list1);
test1(list2);
test1(list3);
test2(list1);
test2(list2);
// test2(list3);
}
//Dog和它的子类
public static void test1(List<? extends Dog> list){
System.out.println(list);
}
//Dog和它的父类
public static void test2(List<? super Dog> list){
System.out.println(list);
}
}
class Aniaml{}
class Dog extends Aniaml{}
class TaiDi extends Dog{}
/**
* 测试边遍历、边删除(使用迭代器Iterator进行遍历删除)
*/
public class IteratorTest {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("bad");
list.add("bag");
System.out.println(list);
//边遍历边删除时,容器的size会发生变化
// for(int i=0;i<list.size();i++){
// String temp=list.get(i);
//
// if(temp.startsWith("b")){
// list.remove(i);
// }
// System.out.println("size:"+list.size());
// }
//使用迭代器对象,他始终指向下一个元素,不关心容器的整体变化
for(Iterator<String> iter=list.iterator();iter.hasNext();){
String temp=iter.next();
if(temp.startsWith("b")){
iter.remove();
}
}
System.out.println(list);
}
}
七、手写容器
package com.myproject;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义的MyList接口,模仿的是List接口
* @param <E>
*/
public interface MyList<E> {
// List list=new ArrayList();
int size();
boolean isEmpty();
void add(E obj);
public void add(int index,E obj);
public E set(int index,E obj);
public E get(int index);
public boolean contains(E obj);
Object[] toArray();
boolean remove(E obj);
void remove(int index);
void clear();
}
package com.myproject;
import java.util.Arrays;
public class MyArrarList<E> implements MyList<E> {
private int size;
private Object[] elementData;
public static void main(String[] args) {
MyArrarList<String> myList=new MyArrarList<>(10);
System.out.println(myList);
myList.add("aa");
myList.add("bb");
myList.add("cc");
myList.add("dd");
myList.add("ee");
myList.add("ff");
myList.add(2,"xrm");
myList.set(2,"zs");
String str=myList.get(2);
System.out.println(str);
System.out.println(myList.contains("eee"));
System.out.println(myList.toArray());
myList.remove(2);
myList.remove("dd");
System.out.println(myList);
myList.clear();
}
public MyArrarList() {
this(10);
}
public MyArrarList(int initialCapacity) {
if(initialCapacity<0){
try {
throw new Exception("容器初始化大小不能为负数!");
} catch (Exception e) {
e.printStackTrace();
}
}
elementData=new Object[initialCapacity];
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public void add(E obj) {
ensureCapacity();
elementData[size]=obj;
size++;
}
@Override
public void add(int index, E obj) { //在索引位置插入一个元素,其余元素后移
rangeCheck(index);
ensureCapacity();
System.arraycopy(elementData,index,elementData,index+1,size-index);
elementData[index]=obj;
size++;
}
//检查索引是否超出范围
private void rangeCheck(int index){
//索引是否合法的判断
if(index<0 || index==size){
try {
throw new Exception("索引必须位于0到size-1之间");
} catch (Exception e) {
e.printStackTrace();
}
}
}
//检查容量,判断是否需要扩充
private void ensureCapacity(){
if(size==elementData.length){ //需要数组扩容
Object[] newArray=new Object[elementData.length*2+1];
System.arraycopy(elementData,0,newArray,0,elementData.length);
elementData=newArray;
}
}
@Override
public E set(int index, E obj) { //在指定索引位置替换元素,并将旧的元素返回
rangeCheck(index);
Object oldValue=elementData[index];
elementData[index]=obj;
return (E)oldValue;
}
@Override
public E get(int index){
rangeCheck(index);
return (E)elementData[index];
}
@Override
public boolean contains(E obj) {
for(int i=0;i<size;i++){
if(elementData[i].equals(obj)){
return true;
}
}
return false;
}
@Override
public Object[] toArray() {
return elementData;
}
@Override
public boolean remove(E obj) { //删除指定的对象
for(int i=0;i<size;i++){
if(elementData[i].equals(obj)){
remove(i);
return true;
}
}
return false;
}
@Override
public void remove(int index){
rangeCheck(index);
//删除指定位置的对象
int numRemove=size-(index+1);
if(numRemove>0){
System.arraycopy(elementData,index+1,elementData,index,numRemove);
}
size--;
elementData[size]=null;
}
@Override
public void clear() {
for(int i=0;i<size;i++){
elementData[i]=null;
}
size=0;
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("[");
for(int i=0;i<size;i++){
sb.append(elementData[i]+"\t");
}
sb.append("]");
return sb.toString();
}
}
八、LinkedList类
/**
* 自定义的MyList接口,模仿的是List接口
* @param <E>
*/
public interface MyList<E> {
// List list=new ArrayList();
int size();
boolean isEmpty();
void add(E obj);
public void add(int index,E obj);
public E set(int index,E obj);
public E get(int index);
public boolean contains(E obj);
Object[] toArray();
boolean remove(E obj);
void remove(int index);
void clear();
}
public class MyLinkedList<E> implements MyList<E> {
private int size;
private Node first; //第一个节点
private Node last; //最后一个节点
public static void main(String[] args) {
MyLinkedList<String> mlList=new MyLinkedList<>();
mlList.add("aa");
mlList.add("bb");
mlList.add("cc");
mlList.add("dd");
Node node=mlList.node(2);
mlList.add("zhangsan");
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public void add(E obj) {
Node n=new Node();
//给容器增加一个obj,实际上增加一个节点(使用这个节点存储obj)
if(first==null){
//增加第一个节点
n.setPrevious(null);
n.setObj(obj);
n.setNext(null);
first=n;
last=n;
}else{
n.setPrevious(last);
n.setObj(obj);
n.setNext(null);
last.setNext(n);
last=n;
}
size++;
}
private Node node(int index){
rangeCheck(index);
Node tmp=null;
if(first!=null){
if(index<(size>>1)){
tmp=first;
for(int i=0;i<index;i++){
tmp=tmp.next;
}
}else{
tmp=last;
for(int i=size-1;i>index;i--){
tmp=tmp.previous;
}
}
}
return tmp;
}
@Override
public void add(int index, E obj) {
Node temp=node(index);
Node newNode=new Node();
newNode.obj=obj;
if(temp!=null){
Node up=temp.previous;
up.next=newNode;
newNode.previous=up;
newNode.next=temp;
temp.previous=newNode;
}
size++;
}
@Override
public E set(int index, E obj) {
rangeCheck(index);
Node tmp=node(index);
tmp.obj=obj;
return (E) tmp.obj;
}
@Override
public E get(int index) {
return (E)node(index).obj;
}
@Override
public boolean contains(E obj) {
for(int i=0;i<size;i++){
if(node(i).obj.equals(obj)){
return true;
}
}
return false;
}
@Override
public Object[] toArray() {
Object[] objs=new Object[size];
for(int i=0;i<size;i++){
objs[i]=node(i).obj;
}
return objs;
}
@Override
public boolean remove(E obj) {
for(int i=0;i<size;i++){
if(node(i).obj.equals(obj)){
remove(i);
return true;
}
}
return false;
}
@Override
public void remove(int index) {
rangeCheck(index);
Node temp=node(index);
if(temp!=null){
Node up=temp.previous;
Node next=temp.next;
up.next=next;
next.previous=up;
size--;
}
}
@Override
public void clear() {
for(int i=0;i<size;i++){
remove(i);
}
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("[");
for(int i=0;i<size;i++){
sb.append(node(i).obj+"\t");
}
sb.append("]");
return sb.toString();
}
//检查索引是否超出范围
private void rangeCheck(int index){
//索引是否合法的判断
if(index<0 || index==size){
try {
throw new Exception("索引必须位于0到size-1之间");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 链表中的节点类
*/
class Node{
Node previous; //上一个节点
Node next; //下一个节点
Object obj; //真正存储的信息
public Node() {
}
public Node(Node previous, Node next, Object obj) {
this.previous = previous;
this.next = next;
this.obj = obj;
}
public Node getPrevious() {
return previous;
}
public void setPrevious(Node previous) {
this.previous = previous;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
九、HashMap类
public interface MyMap<k,v> {
/**
* 自定义Map接口
* @param key
* @param value
*/
public void put(k key,v value);
public v get(k key);
public boolean containsKey(k key);
public boolean containsValue(v value);
public void remove(k key);
public int size();
public boolean isEmpty();
}
/**
* 手工实现的HashMap
*/
public class MyHashMap<k,v> implements MyMap<k,v> {
public static final int INITIAL_CAPACITY=16;
private int size;
private Entry[] table;
public MyHashMap(){
table=new Entry[INITIAL_CAPACITY];
}
public static void main(String[] args) {
MyHashMap<String,String> map=new MyHashMap<>();
System.out.println(map);
map.put("a","AAA");
map.put("b","BBB");
map.put("c","CCC");
map.put("d","DDD");
map.put("a","aaa");
System.out.println(map.get("c"));
System.out.println(map);
map.remove("a");
System.out.println(map);
}
private int hash(k key){
int hashCode=key.hashCode(); //有可能为负数
hashCode=hashCode<0?-hashCode:hashCode; //确保正数
// int index=hashCode/hashCode; //最差的算法,hashCode退化成链表
// int index=hashCode%table.length; //早期的jdk就是这样的算法
return hashCode&(table.length-1); //位运算,效率较高
}
@Override
public void put(k key, v value) {
int index=hash(key);
Entry entry=new Entry(key,value,index,null);
if(table[index]==null){
table[index]=entry;
}else{
Entry e=table[index];
Entry last=e;
while(e!=null){
if(e.key.equals(key)){
e.value=value; //如果Key相等,则直接覆盖value
return;
}
last=e; //保存最后一个
e=e.next;
}
//上面整个循环结束,没有return,则说明整个单向链表中没有Entry的key和传入的key相等
//则添加到链表的最后
last.next=entry;
}
size++;
}
@Override
public v get(k key) {
int index=hash(key);
if(table[index]!=null){
Entry e=table[index];
while (e!=null){
if(e.key.equals(key)){
return (v)e.value; //如果key相等,则返回对应的value
}
e=e.next;
}
}
return null;
}
@Override
public boolean containsKey(k key) {
return false;
}
@Override
public boolean containsValue(v value) {
return false;
}
@Override
public void remove(k key) {
int index=hash(key);
if(table[index]!=null){
Entry e=table[index];
Entry pre=null; //上一个节点
while(e!=null){
if(e.key.equals(key)){
if(pre==null){
table[index]=e.next; //它的下一个节点前移
}else{
pre.next=e.next; //相当于把e移除
size--;
}
}
pre=e;
e=e.next;
}
}
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("[");
for(Entry e:table){
while(e!=null) {
sb.append("{"+e.key+":"+e.value+"}\t");
e=e.next;
}
}
sb.append("]");
return sb.toString();
}
}
class Entry<k,v>{
k key;
v value;
int hash;
Entry next; //下一个节点
public Entry() {
}
public Entry(k key, v value, int hash, Entry next) {
this.key = key;
this.value = value;
this.hash = hash;
this.next = next;
}
}