java超大容器_java容器超详细

前言

java容器是前人为我们提供的一套用于存储数据和对象的工具。如果你学过C++的STL,可以与之类比。java容器又可以称为Java Collection Framework(JCF)。里面除了存储对象的容器之外,还提供了一套用于处理和操作容器里面的对象的一套工具类。

整体框架:

a979983b0f3f7a20df95e8ae9a469301.png

下面将介绍List、Set、Map以及工具类Collections和Arrays。

List

58c8945bf8da43f91577005f8910e6fd.png

List:列表,是一个接口。它的实现类常用的有LinkedList、ArrayList和Vector。

LinkedList

LinkedList采用双向链表实现的列表,因此可以被用作队列、堆栈、双端队列;顺序访问高效,随机访问性能较差、适用于需要经常添加和删除的数据。

LinkedList不支持同步

package 常用数据结构;

import java.util.Iterator;

import java.util.LinkedList;

/**

* @author pony

* @date 2020/4/28

*/

public class LinkedListTest {

public static void main(String[] args) {

LinkedList linked = new LinkedList<>();

for(int i=0;i<10;++i){

linked.add(i);

}

System.out.println(linked.size());

linked.addFirst(10);

linked.add(3,20);

linked.remove(3);

LinkedList list = new LinkedList<>();

for(int i=0;i<100000;++i)

list.add(i);

traverseByIterator(list);

traverseByIndex(list);

traverseByFor(list);

}

private static void traverseByFor(LinkedList list) {

long start = System.nanoTime();

for(Integer i:list)

;

long end = System.nanoTime();

System.out.println("for-each遍历:"+(end-start)+"ms");

}

private static void traverseByIndex(LinkedList list) {

long start = System.nanoTime();

for(int i=0;i

list.get(i);

long end = System.nanoTime();

System.out.println("随机索引遍历:"+(end-start)+"ms");

}

private static void traverseByIterator(LinkedList list) {

long start = System.nanoTime();

Iterator iterator = list.iterator();

while (iterator.hasNext())

iterator.next();

long end = System.nanoTime();

System.out.println("迭代器遍历:"+(end-start)+"ms");

}

}

运行结果:

83ab93af937a252628b57a074cbcfd4b.png

ArrayList

ArrayList是采用数组实现的列表,因此它支持随机访问,不适合频繁删除和插入操作。对于需要经常进行查询的数据建议采用此结构。

ArrayList与java数组的一个大的区别是ArrayList能够自动扩容

ArrayList不支持同步

package 常用数据结构;

import java.util.ArrayList;

import java.util.Iterator;

/**

* @author pony

* @date 2020/4/28

*/

public class ArrayListTest {

public static void main(String[] args) {

ArrayList arrayList = new ArrayList<>();

for(int i=0;i<5;++i){

arrayList.add(i); //这里会自动装箱

}

arrayList.add(0); //允许有相同的元素

arrayList.remove(2);

arrayList.add(3,9);

//遍历测试

ArrayList arr1 = new ArrayList<>();

for(int i=0;i<100000;++i){

arr1.add(i);

}

traverseByIterator(arr1);

traverseByIndex(arr1);

traverseByFor(arr1);

}

private static void traverseByFor(ArrayList arr1) {

long start = System.nanoTime();

for(Integer i:arr1)

;

long end = System.nanoTime();

System.out.println("for遍历:"+(end-start)+"ms");

}

private static void traverseByIndex(ArrayList arr1) {

long start = System.nanoTime();

for(int i=0;i

arr1.get(i);

}

long end = System.nanoTime();

System.out.println("随机索引遍历:"+(end-start)+"ms");

}

private static void traverseByIterator(ArrayList arr1) {

long start = System.nanoTime();

Iterator iterator = arr1.iterator();

while (iterator.hasNext())

iterator.next();

long end = System.nanoTime();

System.out.println("迭代器遍历:"+(end-start)+"ms");

}

}

运行结果:

3a958be935b3df47d7684222fd1445d1.png

Vector

Vector用法和ArrayList用法很相似,它们的区别在于Vector是线程同步的而且Vector有另外的遍历方式。这里将不再赘述。

总结

对于不同的数据我们应该根据其特点采用不同的list,而不是一中list用到底。要学会灵活使用。

Set

Set:集合,和数学中的集合类似。

特点:

确定性:对任一对象都能判定它是否属于某一个集和

互异性:一个集和中不会存在两个相同(内容相同)的对象

无序性:集和里面的元素没有顺序

3af9ab13960808b3b5832915bdde801f.png

HashSet、LinkedHashSet、TreeSet里面存放的都要是对象,不能是基本数据类型。

HashSet

基于散列函数的集和,采用HashMap实现,可以容纳null元素,不支持同步(可以通过Collections.synchronizedSet(new HashSet()来使它同步)

package 常用数据结构;

import java.util.HashSet;

import java.util.Iterator;

/**

* @author pony

* @date 2020/4/28

*/

public class HashSetTest {

public static void main(String[] args) {

HashSet hs = new HashSet<>();

for(int i=0;i<5;++i)

hs.add(i);

hs.add(1); //无效的语句,因为集合中已经有1了。

hs.add(null); //可以容纳null元素

/**

* 测试两种遍历

*/

HashSet hs1 = new HashSet<>();

for(int i=0;i<100000;++i)

hs1.add(i);

long start = System.nanoTime();

Iterator iterator = hs1.iterator();

while (iterator.hasNext())

iterator.next();

long end = System.nanoTime();

System.out.println("迭代器遍历:"+(end-start)+"ms");

start = System.nanoTime();

for(Integer item:hs1)

;

end = System.nanoTime();

System.out.println("for-each遍历:"+(end-start)+"ms");

}

}

运行结果:

0482f53c778c72588429f5840ca8362c.png

HashLinkedSet

继承HashSet ,基于散列函数和双向链表的集和,可以容纳null元素,通过双向链表维护了插入顺序,从而支持排序,但不支持同步(可以通过Collections.synchronizedSet(new HashSet()来使它同步)

代码和上面类似。把HashSet改成LinkedHashSet即可

运行结果:

d8263fdf2650d3609f4759700b36b948.png

TreeSet

基于树结构的集和,印次支持排序,不能容纳null元素,同样不支持同步

package 常用数据结构;

import java.util.TreeSet;

/**

* @author pony

* @date 2020/4/28

*/

public class TreeSetTest {

public static void main(String[] args) {

TreeSet ts = new TreeSet<>();

for(int i=0;i<10;++i)

ts.add(i);

ts.add(100);

ts.add(20);

ts.add(45);

for(Integer item:ts)

System.out.println(item);

// ts.add(null); //错误,不支持添加null元素

ts.add(1); //重复

}

}

db72953d4f195e2f99c4d9e9233b1d78.png

总结

判定是否是重复元素的原则

HashSet、LinkedHashSet

判断两个对象的hashcode()是否相同,如果不同,返回flase

如果hashcode()相同,则调用equals()方法判断内容是否相同。相同返回true,不同返回flase

package 常用数据结构;

import java.util.HashSet;

import java.util.LinkedHashSet;

/**

* @author pony

* @date 2020/4/28

*/

public class HashSetEqualsRuleTest {

public static void main(String[] args) {

HashSet cats = new HashSet<>();

cats.add(new Cat(1));

cats.add(new Cat(2)); //这里将看成是两个对象,因为hashcode方法返回的值不一样

cats.add(new Cat(2));

System.out.println(cats.size()); //3

//重写了hashcode()和equals()

HashSet dogs = new HashSet<>();

dogs.add(new Dog(1));

dogs.add(new Dog(2)); //这里是一个对象,因为重写了它的hashcode方法使得返回值一样

dogs.add(new Dog(2));

System.out.println(dogs.size()); //2

LinkedHashSet cats1 = new LinkedHashSet<>();

cats1.add(new Cat(1));

cats1.add(new Cat(2));

cats1.add(new Cat(2));

System.out.println(cats1.size()); //3

//重写了hashcode()和equals()

LinkedHashSet dogs1 = new LinkedHashSet<>();

dogs1.add(new Dog(1));

dogs1.add(new Dog(2));

dogs1.add(new Dog(2));

System.out.println(dogs1.size()); //2

}

}

class Cat{

public int size;

public Cat(int size) {

this.size = size;

}

}

class Dog {

public int size;

public Dog(int size) {

this.size = size;

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

Dog dog = (Dog) o;

return size == dog.size;

}

@Override

public int hashCode() {

return size;

}

@Override

public String toString() {

return "Dog{" +

"size=" + size +

'}';

}

}

TreeSet

添加到TreeSet里面的元素都必须实现comparable接口。因为在添加元素时会调用接口里面的compareTo()方法来比较是否是同一个元素。

package 常用数据结构;

import java.util.TreeSet;

/**

* @author pony

* @date 2020/4/28

*/

public class TreeSetEqualsRuleTet {

public static void main(String[] args) {

// TreeSet cats = new TreeSet<>();

// cats.add(new Cat(1)); //会报错,因为没有实现Compareable接口

// cats.add(new Cat(1));

// System.out.println(cats.size());

TreeSet tiggers = new TreeSet<>();

tiggers.add(new Tigger(1));

tiggers.add(new Tigger(2));

tiggers.add(new Tigger(1));

System.out.println(tiggers.size());

}

}

class Tigger implements Comparable{

public int size;

public Tigger(int size) {

this.size = size;

}

public int getSize() {

return size;

}

@Override

public int compareTo(Object o) {

System.out.println("in Tigger compareTo");

return size-((Tigger)o).getSize();

}

}

运行结果:

5361ed90026efa27e674b0a6d09a25bb.png

Map

Map是一类重要的数据结构。类似于数学中的函数,key对应自变量x、value对应因变量y、散列函数对用f。

66dcc16d6a52660ef86c230d1a841a23.png

Hashtable

key和value都不能为空,HashTable是线程安全的、同步的,但只适合用于小数据量

package 常用数据结构;

import java.util.Hashtable;

import java.util.Iterator;

import java.util.Map;

/**

* @author pony

* @date 2020/4/28

*/

public class HashtableTest {

public static void main(String[] args) {

Hashtable ht = new Hashtable<>();

// ht.put(1,null); 报错

// ht.put(null,"1"); 报错

// ht.put(null,null); 报错

ht.put(1,"111");

ht.put(2,"222");

ht.put(3,"3333");

ht.contains("111");

ht.containsValue("111");

ht.containsKey(0);

/**

* 三种遍历方式

*/

ht.clear();

for(int i=0;i<100000;++i)

ht.put(i,"aaaa");

//第一种:Entry迭代器遍历

long start = System.nanoTime();

Iterator> iterator = ht.entrySet().iterator();

while (iterator.hasNext()) {

Map.Entry next = iterator.next();

next.getKey();

next.getValue();

}

long end = System.nanoTime();

System.out.println("Entry迭代器遍历:"+(end-start));

//第二种:keySet迭代器遍历

start=System.nanoTime();

Iterator iterator1 = ht.keySet().iterator();

while (iterator1.hasNext()){

Integer key = iterator1.next();

String value = ht.get(key);

}

end = System.nanoTime();

System.out.println("keySet迭代器遍历:"+(end-start));

}

}

运行结果:

bf040d48c1b62f7e8a0943ef90993754.png

HashMap

HashMap允许有null,不支持同步(支持通过Collections.synchronizedMap(new Map() 实现同步),所以线程不安全。但可以存储大量数据

package 常用数据结构;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

/**

* @author pony

* @date 2020/4/28

*/

public class HashMapTest {

public static void main(String[] args) {

HashMap ht = new HashMap<>();

ht.put(1,null);

ht.put(null,"1");

ht.put(null,null);

ht.put(1,"111");

ht.put(2,"222");

ht.put(3,"3333");

ht.containsValue("111");

ht.containsKey(0);

Iterator iterator2 = ht.keySet().iterator();

while (iterator2.hasNext()){

Integer key = iterator2.next();

System.out.println(key+":"+ht.get(key));

}

/**

* 三种遍历方式

*/

ht.clear();

for(int i=0;i<100000;++i)

ht.put(i,"aaaa");

//第一种:Entry迭代器遍历

long start = System.nanoTime();

Iterator> iterator = ht.entrySet().iterator();

while (iterator.hasNext()) {

Map.Entry next = iterator.next();

next.getKey();

next.getValue();

}

long end = System.nanoTime();

System.out.println("Entry迭代器遍历:"+(end-start));

//第二种:keySet迭代器遍历

start=System.nanoTime();

Iterator iterator1 = ht.keySet().iterator();

while (iterator1.hasNext()){

Integer key = iterator1.next();

String value = ht.get(key);

}

end = System.nanoTime();

System.out.println("keySet迭代器遍历:"+(end-start));

}

}

运行结果:

a28db304fb30c59f77fb43e743e7f258.png

LinkedHashMap

基于双向链表用于维持插入顺序的HashMap,继承自HashMap

TreeMap

基于红黑树的Map,可以根据key的自然排序或者compareTo方法排序输出

Properties

继承自Hashtable。特有的方法有load()、store()等等。

总结

Map的种类有很多,根据实际情况选择合适的Map。

工具类

Arrays

Arrays处理的对象是数组,常用的方法包括排序sort、查找binarySearch、拷贝copy等等

package 常用数据结构;

import java.util.Arrays;

import java.util.Random;

import java.util.stream.IntStream;

/**

* @author pony

* @date 2020/4/28

*/

public class ArraysTest {

public static void main(String[] args) {

testSort();

testSearch();

testFill();

testCopy();

testEquality();

}

private static void testEquality() {

int[] a = new int[5];

int[] b = new int[5];

Arrays.fill(a,1);

Arrays.fill(b,1);

System.out.println(Arrays.equals(a,b));

b[1]=3;

System.out.println(Arrays.equals(a,b));

}

private static void testCopy() {

Random random = new Random();

IntStream ints = random.ints(20,1,100);

int[] a = ints.toArray();

for(int i:a)

System.out.println(i);

int[] ints1 = Arrays.copyOf(a, 4);

for(int i:ints1)

System.out.println(i);

}

private static void testFill() {

int[] a = new int[10];

Arrays.fill(a,2,8,100);

for(int i:a)

System.out.println(i);

}

private static void testSearch() {

Random random = new Random();

int[] ints = random.ints(5,1,100).toArray();

ints[ints.length-1]=100;

int i = Arrays.binarySearch(ints, 100);

System.out.println("100 in "+i);

}

private static void testSort() {

Random random = new Random();

IntStream ints = random.ints(20,1,100);

int[] a = ints.toArray();

System.out.println("排序前:");

for(int i:a)

System.out.println(i);

Arrays.sort(a);

System.out.println("排序后:");

for(int i:a)

System.out.println(i);

}

}

Collections

Collections可以操作collections接口及其所有子类、常用的用法和Arrays差不多。但它的sort方法要求被排序对象实现了compareable接口或者传入一个compactor对象(主要针对某些类不能去被修改)

总结

Arrays和Collections着两个工具类能够帮我们做很多事情,所以要熟练的应用。避免重复造轮子。

总结

写到这,容器的基本知识应该都了解的差不多了,但这只能算是对容器入门了。只是学会了如何去使用。建议以后多多去查阅API和源码。了解其内部是如何实现这些结构的。当你能够自己写出来这些容器的实现时,才算真正的掌握了java容器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值