【JAVA学习】四、容器

四、容器

1. 数组

是一个简单的线性序列,速度快效率高。但是不够灵活,比如容量。
在这里插入图片描述

  1. Set没有顺序不可重复。
  2. List有顺序可重复。
  3. Map存放键值对。

2. 泛型

泛型的本质是数据类型的参数化,可以把泛型理解为一个形参,在调用泛型时必须传入实际类型。

class Solution {
    public static void main(String[] args) {
        MyCollection<String> mc = new MyCollection<>();
        mc.set("tsc",0);
        mc.set("123",1);
        String b = mc.get(0);
        System.out.println(b);
    }
}
class MyCollection<E>{
    Object[] objs = new Object[5];

    public void set(E obj, int index){
        objs[index] = obj;
    }

    public E get(int index){
        return (E) objs[index];
    }
}

实际上容器使用的接口在定义的时候使用的都是泛型。

3. Collection接口

class Solution {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        System.out.println(c.size());
        System.out.println(c.isEmpty());
        c.add("tsc");
        c.add("abc");
        System.out.println(c);
        //这里是把该对象地址移除出容器,但是对象还在
        c.remove("abc");
        System.out.println(c);
        Object[] objs = c.toArray();
        System.out.println(objs);
        System.out.println(c.contains("tsc"));
         //移除所有元素
        c.clear();
        System.out.println(c);
    }
}

在这里插入图片描述

4. ArrayList

class Solution {
    public static void main(String[] args) {
        List<String> list01 = new ArrayList<>();
        list01.add("aa");
        list01.add("bb");
        list01.add("cc");

        List<String> list02 = new ArrayList<>();
        list02.add("aa");
        list02.add("dd");
        list02.add("ee");

        System.out.println("list01:" + list01);
        list01.addAll(list02);
        System.out.println("list01:" + list01);
        list01.retainAll(list02);
        System.out.println("list01:" + list01);
        list01.removeAll(list02);
        System.out.println("list01:" + list01);
        list01.addAll(list02);
        System.out.println(list01.containsAll(list02));
    }
}

在这里插入图片描述
List是有序,可重复的容器。

  1. 有序:List中的每个元素都有索引标记,可以根据元素的索引标记访问元素,从而精确控制这些元素。
  2. 可重复:允许加入重复的元素。
    List常用的实现类有,ArrayList,LinkedList和Vector。
class Solution {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("A");
        list.add("A");
        list.add("A");
        System.out.println(list);
        //索引相关方法
        list.add(2,"B");
        System.out.println(list);
        list.remove(3);
        System.out.println(list);
        list.set(2,"C");
        System.out.println(list);
        System.out.println(list.get(2));
        list.add("C");
        System.out.println(list);
        System.out.println(list.indexOf("C"));
        System.out.println(list.lastIndexOf("C"));
    }
}

在这里插入图片描述
ArrayList底层是用数组实现的,查询效率高,增删改效率低,线程不安全。一般使用它,因为查询的情况多。
数组长度是有限的,ArrayList可以存放任意数量的对象,采取的是数组扩容的技术。定一一个更长的数组(原来的1.5倍)把原来的拷过来,新的加在后面。

ArrayList添加方法
public class MyArrayList<E> {
    private Object[] elementData;
    private int size;
    private static final int DEFALT_CAPACITY = 10;
    public MyArrayList(){
        elementData = new Object[DEFALT_CAPACITY];
    }
    public MyArrayList(int capacity){
        elementData = new Object[capacity];
    }
    public void add(E obj){
        elementData[size ++] = obj;
    }
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i = 0 ; i < size ; i ++){
            sb.append(elementData[i] + ",");
        }
        sb.setCharAt(sb.length() - 1,']');
        return sb.toString();
    }
    public static void main(String[] args) {
        MyArrayList m1 = new MyArrayList(20);
        m1.add("a");
        m1.add("b");
        System.out.println(m1);
    }
}
数组扩容
public class MyArrayList<E> {
    private Object[] elementData;
    private int size;
    private static final int DEFALT_CAPACITY = 10;
    public MyArrayList(){
        elementData = new Object[DEFALT_CAPACITY];
    }
    public MyArrayList(int capacity){
        elementData = new Object[capacity];
    }
    public void add(E obj){
        //什么时候扩容
        if (size == elementData.length){
            //扩容操作
            Object[] newArray = new Object[elementData.length + (elementData.length >> 1)];
            System.arraycopy(elementData,0,newArray,0,elementData.length);
            elementData = newArray;
        }
        elementData[size ++] = obj;
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i = 0 ; i < size ; i ++){
            sb.append(elementData[i] + ",");
        }
        sb.setCharAt(sb.length() - 1,']');
        return sb.toString();
    }
    public static void main(String[] args) {
        MyArrayList m1 = new MyArrayList(20);
        m1.add("a");
        m1.add("b");
        System.out.println(m1);
        for (int i = 0; i < 40; i++) {
            m1.add("aa");
        }
        System.out.println(m1);
    }
}
增加set,get方法
public class MyArrayList<E> {
    private Object[] elementData;
    private int size;
    private static final int DEFALT_CAPACITY = 10;
    public MyArrayList(){
        elementData = new Object[DEFALT_CAPACITY];
    }
    public MyArrayList(int capacity){
        elementData = new Object[capacity];
    }
    public void add(E obj){
        //什么时候扩容
        if (size == elementData.length){
            //扩容操作
            Object[] newArray = new Object[elementData.length + (elementData.length >> 1)];
            System.arraycopy(elementData,0,newArray,0,elementData.length);
            elementData = newArray;
        }
        elementData[size ++] = obj;
    }
    public E get(int index){
        if (index < 0 || index > size - 1){
            throw new RuntimeException("索引不合法");
        }
        return (E)elementData[index];
    }
    public void set(E element, int index){
        if (index < 0 || index > size - 1){
            throw new RuntimeException("索引不合法");
        }
        elementData[index] = element;
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i = 0 ; i < size ; i ++){
            sb.append(elementData[i] + ",");
        }
        sb.setCharAt(sb.length() - 1,']');
        return sb.toString();
    }
    public static void main(String[] args) {
        MyArrayList m1 = new MyArrayList(20);
        m1.add("a");
        m1.add("b");
        System.out.println(m1);
        for (int i = 0; i < 40; i++) {
            m1.add("aa");
        }
        System.out.println(m1);
        System.out.println(m1.get(4));
        m1.set("bb",11);
        System.out.println(m1);
    }
}
remove
public void remove(E element){
        //element将它和所有元素比较,获得第一个为true的返回
        for (int i = 0; i < size; i++) {
            if (element.equals(get(i))){ //容器中所有的比较操作,都是用equals而不是==
                //将该元素从此处移除
                remove(i);
            }
        }
    }
    public void remove(int index){
        int numMoved = elementData.length - index - 1;
        if (numMoved > 0){
            System.arraycopy(elementData,index + 1,elementData,index,numMoved);
            elementData[size - 1] = null;
        }
        if (numMoved == 0){
            elementData[size - 1] = null;
        }
        size --;
    }
    public int size(){
        return size;
    }
    public boolean isEmpty(){
        return size == 0 ? true : false;
    }

5. LinkedList

底层是用双向链表实现的存储,查询效率低,增删效率高,线程不安全。
双向链表结构:

class Node {
	Node previous;
	Object element;
	Node next;
}
public class MyLinkedList<E> {
    private Node first;
    private Node last;
    private int size;
    public void add(Object obj){
        Node node = new Node(obj);
        if (first == null){
            first = node;
            last = node;
        }else {
            node.previous = last;
            node.next = null;
            last.next = node;
            last = node;
        }
        size ++;
    }
    public void insert(int index, E obj){
        Node newNode = new Node(obj);
        Node temp = getNode(index);
        if (index == 0){
            first.previous = newNode;
            newNode.next = first;
            first = newNode;
            size ++;
            return;
        }
        if (index == size){
            add(obj);
            return;
        }
        if (temp != null){
            Node up = temp.previous;
            up.next = newNode;
            newNode.previous = up;

            newNode.next = temp;
            temp.previous = newNode;
            size ++;
        }
    }
    public void remove(int index){
        Node temp = getNode(index);
        if (temp != null){
            Node up = temp.previous;
            Node down = temp.next;
            if (up != null){
                up.next = down;
            }
            if (down != null){
                down.previous = up;
            }
            if (index == 0){
                first = down;
            }
            if (index == size - 1){
                last = up;
            }
            size --;
        }
    }
    public E get(int index){
        if (index < 0 || index > size - 1){
            throw new RuntimeException("索引不合法");
        }
        Node temp = getNode(index);
        return (E)temp.element;
    }
    public Node getNode(int index){
        Node temp = null;
        if (index < (size >> 1)) {
            temp = first;
            for (int i = 0; i < index; i++) {
                temp = temp.next;
            }
        }else {
            temp = last;
            for (int i = size - 1; i > index ; i--) {
                temp = temp.previous;
            }
        }
        return temp;
    }


    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        Node temp = first;
        while (temp != null){
            sb.append(temp.element + ",");
            temp = temp.next;
        }
        sb.setCharAt(sb.length() - 1,']');
        return sb.toString();
    }

    public static void main(String[] args) {
        MyLinkedList list = new MyLinkedList();
        list.add("a");
        list.add("b");
        list.add("c");
        System.out.println(list);
        System.out.println(list.get(1));
        list.remove(1);
        System.out.println(list);
        list.insert(0,"d");
        System.out.println(list);
        list.insert(3,"k");
        System.out.println(list);
    }
}

6.Vector向量

底层是用数组实现的List,线程安全。相关方法都加了同步检查,线程安全效率低。比如indexof方法就加了synchronized同步标记。

  1. 需要线程安全的时候使用vector。
  2. 不存在线程安全问题时,查找较多使用ArrayList。
  3. 不存在线程安全问题时,增删较多使用LinkedList。

7.Map接口

存储的是键值对,通过键对象找值对象。

public class MyMap {
    public static void main(String[] args) {
        Map<Integer,String> m1 = new HashMap<>();
        m1.put(1,"one");
        m1.put(2,"two");
        System.out.println(m1.get(1));
        System.out.println(m1.size());
        m1.remove(1);
        System.out.println(m1.size());
        System.out.println(m1.containsKey(2));
        System.out.println(m1.containsValue("two"));
        Map<Integer,String> m2 = new HashMap<>();
        m2.put(3,"three");
        m2.put(4,"four");
        m1.putAll(m2);
        System.out.println(m1.size());
        //map中键不能重复,否则新的覆盖旧的
        m1.put(3,"三");
        System.out.println(m1);
    }
}

常用方法
public class MyMap {
    public static void main(String[] args) {
        Employee e1 = new Employee(1,"tsc",20000);
        Employee e2 = new Employee(2,"tscc",30000);
        Employee e3 = new Employee(3,"tsccc",40000);
        Map<Integer,Employee> map = new HashMap<>();
        map.put(1,e1);
        map.put(2,e2);
        map.put(3,e3);
        Employee emp = map.get(1);
        System.out.println(emp.getName());
    }
}
class Employee{
    private int id;
    private String name;
    private double salary;

    public Employee(int id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

8. HashMap

底层使用了哈希表,是一种非常重要的数据结构。本质上就是数组+链表。
key先通过hashcode()方法得到一个数字,这个数字再通过散列函数确定桶进行存储,初始的桶个数是16,大小是可变的。如果桶中的元素达到0.75*数组长度的时候就会调整成为原来的二倍。扩容是很耗时的,需要定义更大的数组并将旧数组内容拷贝到新数组中。
当每个桶中的链表长度大于8时,会变成红黑树。

public class MyHashMap {
    Node2[] table; //桶数组
    int size; //存放的键值对数
    public MyHashMap(){
        table = new Node2[16];
    }
    public void put(Object key,Object value){
        //定义了新的节点对象
        Node2 newNode = new Node2();
        newNode.hash = myHash(key.hashCode(),table.length);
        newNode.key = key;
        newNode.value = value;

        Node2 temp = table[newNode.hash];
        Node2 last = null;
        if (temp == null){
            table[newNode.hash] = newNode;
        }else {
            while (temp != null){
                //判断Key如果重复,则覆盖
                if (temp.key.equals(key)){
                    temp.value = value; //只覆盖value
                    return;
                }else {
                    //key不重复,
                    last = temp;
                    temp = temp.next;
                }
            }
            last.next = newNode;
        }
    }

    public Object get(Object key){
        int hash = myHash(key.hashCode(), table.length);
        Object value = null;
        if (table[hash] != null){
            Node2 temp = table[hash];
            while (temp != null){
                if (temp.key.equals(key)){
                    value = temp.value;
                    break;
                }else {
                    temp = temp.next;
                }
            }
        }
        return value;
    }
    public int myHash(int v,int length){
        return v & (length - 1);//和v%(length-1)作用一样(散列到0-15之间),但是值不一样。效率高
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder("{");
        for (int i = 0; i < table.length; i++) {
            Node2 temp = table[i];
            while (temp != null){
                sb.append(temp.key + ":" + temp.value + ",");
                temp = temp.next;
            }
        }
        sb.setCharAt(sb.length() - 1,'}');
        return sb.toString();
    }

    public static void main(String[] args) {
        MyHashMap m = new MyHashMap();
        m.put(1,"aa");
        m.put(2,"bb");
        m.put(3,"cc");
        m.put(3,"dd");
        m.put(53,"53");
        m.put(69,"69");
        m.put(85,"85");
        System.out.println(m.get(69));
        System.out.println(m);
    }
}
class Node2{
    int hash;
    Object key;
    Object value;
    Node2 next;
}

8.5 TreeMap

public class MyTreeMap {
    public static void main(String[] args) {
        Map<Integer,String> treemap1 = new TreeMap<>();
        treemap1.put(20,"aa");
        treemap1.put(3,"bb");
        treemap1.put(6,"cc");
        // 按照key递增的大小排序
        for (Integer m : treemap1.keySet()){
            System.out.println(treemap1.get(m)); 
        }
    }
}
// bb
// cc
// aa

9. Set

和List一样,继承了Collection接口,是没有顺序不可重复的。没有索引查找只能遍历,不允许加入重复的元素,新元素如果通过equals()方法对比为true则不能加入甚至也只能放入一个null元素不能多个。

public class MyHashSet {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("aa");
        set.add("bb");
        set.add("cc");
        System.out.println(set);
        set.remove("aa");
        System.out.println(set);
        Set<String> set2 = new HashSet<>();
        set2.add("dd");
        set2.addAll(set);
        System.out.println(set2);
    }
}

在这里插入图片描述

public class MyHashSet {
    HashMap map;

    private static final Object PRESENT = new Object();
    public MyHashSet(){
        map = new HashMap();
    }
    public void add(Object o){
        map.put(o,PRESENT);
    }
    public int size(){
        return map.size();
    }
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (Object key : map.keySet()){
            sb.append(key + ",");
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        MyHashSet set = new MyHashSet();
        set.add("aa");
        set.add("bb");
        System.out.println(set);
    }
}

10. 迭代器Iterator

class Solution {
    public static void main(String[] args) {
        testIteratorSet();
    }
    public static void testIteratorList(){
        List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        for (Iterator<String> iter = list.iterator();iter.hasNext();){
            String temp = iter.next();
            System.out.println(temp);
        }
    }
    public static void testIteratorSet(){
        Set<String> set = new HashSet<>();
        set.add("aa");
        set.add("bb");
        set.add("cc");
        for (Iterator<String> iter = set.iterator();iter.hasNext();){
            String temp = iter.next();
            System.out.println(temp);
        }
    }
}
class Solution {
    public static void main(String[] args) {
        testMap2();
    }

    public static void testMap(){
        Map<Integer,String> map1 = new HashMap<>();
        map1.put(1,"a");
        map1.put(2,"b");
        map1.put(3,"c");
        Set<Map.Entry<Integer,String>> ss = map1.entrySet();
        for (Iterator<Map.Entry<Integer,String>> iter = ss.iterator(); iter.hasNext();){
            Map.Entry<Integer,String> temp = iter.next();
            System.out.println(temp.getKey() + " : " + temp.getValue());
        }
    }
    public static void testMap2(){
        Map<Integer,String> map1 = new HashMap<>();
        map1.put(1,"a");
        map1.put(2,"b");
        map1.put(3,"c");
        Set<Integer> keySet = map1.keySet();
        for (Iterator<Integer> iter = keySet.iterator();iter.hasNext();){
            Integer key = iter.next();
            System.out.println(key + " : " + map1.get(key));
        }
    }
}

11. Collections 辅助类的使用

class Solution {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add("t" + i);
        }
        System.out.println(list);
        //随机排列
        Collections.shuffle(list);
        System.out.println(list);
        //逆序
        Collections.reverse(list);
        System.out.println(list);
        //递增排序
        Collections.sort(list);
        System.out.println(list);
        //二分法查找
        System.out.println(Collections.binarySearch(list,"t2"));
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值