Java中的集合

本文深入解析Java集合框架,包括Collection和Map两大类,探讨List、Set、Queue的不同特性,以及HashMap、HashSet、TreeSet的工作原理和使用场景。通过具体代码示例,展示不同集合类在实际应用中的行为差异。
摘要由CSDN通过智能技术生成

Java容器类类库的用途是"保存对象",并将其划分为两个不同的概念:

1) Collection
一组"对立"的元素,通常这些元素都服从某种规则
   1.1) List:有序可重复
   1.2) Set:无序不可重复
   1.3) Queue保持一个队列(先进先出)的顺序
2) Map
一组成对的"键值对"对象

在这里插入图片描述

1. Set

Set集合中对象不可重复,因此当试图添加两个相同元素时,add()方法返回false/元素不可加入;
Set集合中对象必须重写hashCode()方法和equals()方法;

1.1 HashSet

按照Hash算法存储结合元素—>具有良好的存取/查找性能;

  1. 添加元素时,调用hashCode()方法计算对象的hashCode值;
  2. 根据hashCode值决定对象的存储位置—>元素存储顺序和添加顺序可能不一致(LinkedHashSet可保证);
  3. HashSet判断元素相等的标准:equal()方法相等/hashCode()方法返回值相同;
  4. Hash算法/哈希/散列:通过计算元素的hashCode值获取元素的存储位置—>价值在于存取/查找速度快
    与数组相比,HashSet索引不需要连续,可自由增加HashSet长度;

1.2 LinkedHashSet

HashSet的子类,LinkedHashSet也是根据元素的hashCode值决定其存储位置;
同时使用链表维护元素的添加次序—>性能略低于HashSet的性能;

1.3 TreeSet

TreeSet实现SortSet接口,
TreeSet采用红黑树(red-black tree)存储集合元素,排序规则支持自然排序/定制排序;
TreeSet存储对象必须实现Comparable接口;

1.4 测试

HashSet测试

public class HashSetTestCase{
	static class A {
		private String name;

		public A(String name) {
			this.name = name;
		}
		
		@Override
		public boolean equals(Object obj) {
			A other = (A)obj;
			return name.equals(other.name);
		}

		@Override
		public String toString() {
			return "A [name=" + name + "]";
		}
	}
	static class B {
		private String name;

		public B(String name) {
			this.name = name;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			return result;
		}

		@Override
		public String toString() {
			return "B [name=" + name + "]";
		}
	}
	static class C {
		private String name;
		
		public C(String name) {
			this.name = name;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			C other = (C)obj;
			return name.equals(other.name);
		}

		@Override
		public String toString() {
			return "C [name=" + name + "]";
		}
	}
	
	public static void main(String[] args) {
		A a1 = new A("1");
		A a2 = new A("1");
		B b1 = new B("1");
		B b2 = new B("1");
		C c1 = new C("1");
		C c2 = new C("1");
		
		System.out.println(a1 == a2);
		System.out.println(a1.equals(a2));
		System.out.println(b1 == b2);
		System.out.println(b1.equals(b2));
		System.out.println(c1 == c2);
		System.out.println(c1.equals(c2));
		
		HashSet<A> A1 = new HashSet<A>();
		A1.add(a1);
		A1.add(a2);
		HashSet<B> B1 = new HashSet<HashSetTestCase.B>();
		B1.add(b1);
		B1.add(b2);
		HashSet<C> C1 = new HashSet<HashSetTestCase.C>();
		C1.add(c1);
		C1.add(c2);
		System.out.println(A1);
		System.out.println(B1);
		System.out.println(C1);
	}
	
}

输出结果:

false
true
false
false
false
true
[A [name=1], A [name=1]]
[B [name=1], B [name=1]]
[C [name=1]]

LinkedHashSet测试

public class LinkedHashSetTestCase {

	public static void main(String[] args) {
		Set<String> linkedHashSet = new LinkedHashSet<String>();
		Set<String> hashSet = new HashSet<String>();
		linkedHashSet.add("2");
		linkedHashSet.add("3");
		linkedHashSet.add("51");
		linkedHashSet.add("1");
		linkedHashSet.add("21");
		linkedHashSet.add("6");
		linkedHashSet.add("7");
		
		hashSet.add("2");
		hashSet.add("3");
		hashSet.add("51");
		hashSet.add("1");
		hashSet.add("21");
		hashSet.add("6");
		hashSet.add("7");
		
		Iterator<String> linkedHashSetIterator = linkedHashSet.iterator();
		while(linkedHashSetIterator.hasNext()) {
			System.out.print(linkedHashSetIterator.next());
			System.out.print(";");
		}
		System.out.println();
		System.out.println("==============");
		Iterator<String> hashSetIterator = hashSet.iterator();
		while(hashSetIterator.hasNext()) {
			System.out.print(hashSetIterator.next());
			System.out.print(";");
		}
	}
}

输出结果:

2;3;51;1;21;6;7;
==============
1;2;3;6;7;51;21;

TreeSet测试

public class TreeSetTestCase {

	static class A implements Comparable<TreeSetTestCase.A>{

		private String name;
		
		public A(String name) {
			super();
			this.name = name;
		}

		@Override
		public String toString() {
			return "A [name=" + name + "]";
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			A other = (A)obj;
			return name.equals(other.name);
		}

		@Override
		public int compareTo(A o) {
			
			return name.compareTo(o.name);	
		}
	}
	public static void main(String[] args) {
		A a1 = new A("12");
		A a2 = new A("32");
		A a3 = new A("22");
		A a4 = new A("27");
		A a5 = new A("33");
		TreeSet<A> treeSet = new TreeSet<A>();
		treeSet.add(a1);
		treeSet.add(a2);
		treeSet.add(a3);
		treeSet.add(a4);
		treeSet.add(a5);
		System.out.println(treeSet);
	}
}

输出结果

[A [name=12], A [name=22], A [name=27], A [name=32], A [name=33]]

Tree原理扩展:
代码如下:

public V put(K key, V value) {
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        Entry<K,V> parent;
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);// 如果后面的值与树中的值相等,直接取前边的值,重新放到树中,如compareTo中两个值相等,查询处理就只会有一个
            } while (t != null);
        }
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值