Java集合

为什么要学集合?

	当我们要存储一组类型相同的元素时候,我们应该用一个容器来存储,数组就是这样一个容器

那数组有什么缺点么?

	数组一旦定义,长度就不能再变化

然而当我们在开发的实践中,经常需要保存一些变长的数据集合,于是,我们需要一些能够动态增长长度的容器来保存我们的数据.

而我们需要对数据的保存的逻辑可能各种各样,于是就有了各种各样的数据结构,Java中对于各种数据结构的实现,就是我们用到的集合.

集合体系概述

	Java的集合框架是由很多接口,抽象类,具体类组成的,都在java.util包中.	

在这里插入图片描述

Collection接口

collection接口定义了存取一组对象的方法,其子接口set和list分别定义了存储方式

​ --set 中的数据对象没有顺序且不可以重复

​ --list 中的数据对象有顺序且可以 重复

Collention中的方法

	boolean add(Object element);  添加一个元素
	boolean addAll(Collection c);  添加一个集合到调用集合的后边
	boolean remove(Object elemeny);  删除集合指定的第一个元素
	boolean removeAll(Collection c);  删除集合全部元素
	void clear();  清空
	int size();  集合长度
	boolean isEmpty();  集合是否为空
	boolean contains(Object element);   子集
	boolean containsAll(Collection c);  真子集
	boolean retainAll(Collection c);   求交集

List接口及实现类

List继承了Collection接口,有三个实现的类
ArrayList
数组列表,数据采用数组方式存储。
LinkedList
链表
Vector
数组列表,添加同步锁,线程安全的

ArrayList
ArrayList实现了长度可变的数组,在内存中分配连续的空间。

遍历元素和随机访问元素的效率比较高

在这里插入图片描述

这里博主不是写的很全面,大概写了一下

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("a");
        al.add("d");
        al.add("g");
        al.add("b");
        al.add("c");
        al.add("s");
        al.add("z");

        //指定元素添加元素
        al.add(0,"t");

        //排序   要调用排序,那么就得实现Comparator接口,重写conpareTo方法
        al.sort(new ArrayListDemo2());
        System.out.println(al);



        //删除
        al.remove(5);
        System.out.println(al);


    }
}



public class ArrayListDemo1 extends ArrayList {
    public static void main(String[] args) {

        ArrayListDemo1 al = new ArrayListDemo1();
        al.add("a");
        al.add("d");
        al.add("g");
        al.add("b");
        al.add("c");
        al.add("s");
        al.add("z");

        //排序
        al.sort(new ArrayListDemo2());
        System.out.println(al);

        //删除指定区间元素
        al.removeRange(0,5);
        System.out.println(al);
    }
}


public class ArrayListDemo2 implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
}

上述代码运行结果

sort: [a, b, c, d, g, s, t, z]
removeIndex - 5: [a, b, c, d, g, t, z]

LinkedList
LinkedList采用链表存储方式。插入、删除元素时效率比较高

在这里插入图片描述

        LinkedList list1 = new LinkedList();

        for (int i = 1; i < 16; i++) {
            list.add(i);
        }
        System.out.println(list1);
        list1.add(0,0);
        System.out.println(list1);
        list1.addFirst("Yinyongleixing");
        System.out.println(list1);
        list1.addLast("还是引用类型");
        System.out.println(list1);
        System.out.println(list1.removeFirst());
        System.out.println(list1.removeLast());
        System.out.println(list1);
        System.out.println(list1.remove(0));
        System.out.println(list1);
        System.out.println(list1.getFirst());
        System.out.println(list1.getLast());

上述代码运行结果

list1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
list1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
list1: [Yinyongleixing, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
list1: [Yinyongleixing, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 还是引用类型]
Yinyongleixing
removeLast: 还是引用类型
list1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
list1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
getFirst: 0
getLast: 15
Vector
 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。
public class VectorDemo {

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("a");
        al.add("b");
        al.add("c");
        
        al.add("c");
        al.add("d");    
        System.out.println("size: " + al.size());
        System.out.println("remove: " + al.remove("a"));
        System.out.println("getindex a : " + al.indexOf("a"));
    }
}

上述代码运行结果

size: 5
remove: true
getindex a : 1

List接口迭代

 ArrayList al = new ArrayList();
for循环遍历
 通过索引值获取所对应的数据信息
        for (int i = 0; i < al.size(); i++) {
            for (int j = 1; j < al.size()-1; j++) {
                if (al.get(i).equals(al.get(j))){
                    al.remove(i);
                }
            }
        }
增强for循环遍历
	也是通过迭代器的方法获取信息
        for (Object obj: al) {
            if (obj.equals("a")){
                al.remove(obj);
                break;
            }
        }
        System.out.println(al);
迭代器遍历(Itertor)
	通过集合返回迭代器。
		这里要使用到hasnext() 方法
        Iterator it = al.iterator();
        while (it.hasNext()){
            Object obj = it.next();
            it.remove();
        }
        System.out.println(al);

上述代码运行结果

[a, d]
[d]
[]

Set接口

Set接口继承了Collection接口。

 Set中所存储的元素是**不重复**的,但是**是无序**的, Set中的元素是**没有索引**的

HashSet

 HashSet类中的元素不能重复,即彼此调用equals方法比较,都返回false。

​ 底层数据结构是哈希表+链表
​ 哈希表依赖于哈希值存储

  向HashSet中添加元素时是如何判定重复元素?
  
  		底层是双保险的:既要提高判断效率,还要安全可靠
  
 		 首先会获得添加内容hash值,判断hash值在集合中是否存在
  
  			但是内容不同时,hash值可能会相同,那么就不可靠

   				在hash值相同时,会调用equals方法,比较内容是否相同
public class Student implements Comparable<Student> {
    private int num;
    private String name;
    private int age;


    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

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

    public Student(int num, String name, int age) {
        this.num = num;
        this.name = name;
        this.age = age;
    }

         /*
                当hash值出现重复时,会调用eauals方法,进行内容判断
                效率第,安全
         */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;
        Student student = (Student) o;
        return num == student.num &&
                age == student.age &&
                Objects.equals(name, student.name);
    }


    /*
            重写Object类中的hashCode(),来自己操作对象中包含的内容计算hash值
            效率高,会出现重复
     */
    @Override
    public int hashCode() {
        return Objects.hash(num, name, age);
    }
    

    @Override
    public String toString() {
        return "Student{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //以学号排序
    @Override
    public int compareTo(Student o) {
        return this.num-o.num;
    }

}

 public static void main(String[] args) {
        //HashSet无序  不按照输入顺序  有自己特定的方法


        //public native int hashCode();  会调用此方法
        HashSet<String> hs = new HashSet<>();
        hs.add("a");
        hs.add("a");
        hs.add("b");
        hs.add("仲裁");
        hs.add("国有");
        System.out.println(hs);

        HashSet<Student> h = new HashSet<>();
        Student s1 = new Student(101,"tom",20);
        Student s2 = new Student(101,"tom",20);
        Student s3 = new Student(102,"jim",20);
        Student s4 = new Student(103,"bom",19);
        h.add(s1);
        h.add(s2);
        h.add(s3);
        h.add(s4);
        System.out.println(h);

    }

以上代码运行结果

[a, b, 仲裁, 国有]
[Student{num=102, name='jim', age=20}, Student{num=103, name='bom', age=19}, Student{num=101, name='tom', age=20}]

TreeSet

可以给Set集合中的元素进行指定方式的排序。存储的对象必须实现Comparable接口。

TreeSet底层数据结构是二叉树(红黑树是一种自平衡的二叉树)
    public static void main(String[] args) {
        TreeSet<String> ts = new TreeSet();
        ts.add("z");
        ts.add("b");
        ts.add("a");
        ts.add("c");
        ts.add("b");
        ts.add("f");
        System.out.println(ts);

        TreeSet<Student> tst = new TreeSet<>();
        Student s1= new Student(101,"jim",18);
        Student s2= new Student(100,"tom",19);
        Student s3= new Student(109,"bom",101);
        Student s4 = new Student(001,"dom",1);
        tst.add(s1);
        tst.add(s2);
        tst.add(s3);
        tst.add(s4);
        //年龄排序
        System.out.println(tst);
    }

以上代码运行结果

[a, b, c, f, z]
[Student{num=1, name='dom', age=1}, Student{num=100, name='tom', age=19}, Student{num=101, name='jim', age=18}, Student{num=109, name='bom', age=101}]

Map接口

Map接口中常用方法

V put(K key,V value)  
V remove(Object key)
void clear()
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
int size()
V get(Object key)
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()

Map遍历

方式一:根据键找值

获取所有键的集合
遍历键的集合,获取到每一个键
根据键找值
map.keySet();
map.get();
 Map<Integer,String> hm = new LinkedHashMap<>();
 Set<Integer> s = hm.keySet();
 for(Integer i:s){
 	System.out.println(i + "=" + hm.get(i) + ";");
 }

方式二:根据键值对对象找键和值

获取所有键值对对象的集合
遍历键值对对象的集合,获取到每一个键值对对象
根据键值对对象找键和值
  Set<Map.Entry<Integer,String>> set = hm.entrySet();
  for (Map.Entry<Integer,String> entry:set) {
       System.out.print(entry.getKey() + " == " + entry.getValue() + "; ");
  }

TreeMap

TreeMap中所有的元素都保持着某种固定的顺序,
如果需要得到一个有序的Map就应该使用TreeMap,key值所在类必须实现Comparable接口。
适用于按自然顺序或自定义顺序遍历键(key)。
TreeMap根据key值排序,key值需要实现Comparable接口,
重写compareTo方法。TreeMap根据compareTo的逻辑,对
key进行排序。
键是红黑树结构,可以保证键的排序和唯一性

HashMap

HashMap中元素的key值不能重复,即彼此调用equals方法,返回为false。排列顺序是不固定的。

HashTable

 实现了同步
HashMap<Integer,String> map = new HashMap<Integer, String>();
//添加键值对
map.put(1,"张三");
map.put(2,"李四");
map.put(3,"王五");
map.put(4,"赵六");
System.out.println(map);


//都是引用类型
HashMap<String,String> hashMap = new HashMap<String, String>();
hashMap.put("姓名","张三");
hashMap.put("年龄","18");
hashMap.put("籍贯","陕西省");
System.out.println(hashMap);

// V remove(Object key)  删除
hashMap.remove("姓名");
System.out.println(hashMap);
System.out.println(hashMap.get("籍贯"));
System.out.println(hashMap.containsKey("年龄"));
System.out.println(hashMap.containsValue("山西省"));
System.out.println(hashMap.containsValue("陕西省"));
System.out.println(hashMap.size());
System.out.println(hashMap.isEmpty());
System.out.println(hashMap);
hashMap.clear();
System.out.println(hashMap);

以上代码运行结果

{1=张三, 2=李四, 3=王五, 4=赵六}
{姓名=张三, 年龄=18, 籍贯=陕西省}
{年龄=18, 籍贯=陕西省}
陕西省
true
false
true
2
false
{年龄=18, 籍贯=陕西省}
{}

Process finished with exit code 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值