Java集合

01Java集合List篇

简述:集合是什么呢 是用来存储对象存储数据的一种方式能够存储任意长度的对象,长度可以随着元素的增加而增加,随着元素的减少而减少,使用起来方便一些。
集合VS数组:
区别1:
数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
集合只能存储引用数据类型(对象),如果存储基本数据类型时,会自动装箱变成相应的包装类
区别2:
数组长度是固定的,不能自动增长
集合的长度的是可变的,可以根据元素的增加而自动增长

一.集合框架图
在这里插入图片描述
简化图
在这里插入图片描述
简单解释下上图:
1.所有集合类都是在java.util包下,Java集合类主要由两个派生接口,分别是Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口有他们的实现类和一些接口。
2.Collection接口是一组允许重复的对象
3.set和List接口继承Collection接口,set集合元素不重复,List允许重复,维护元素插入顺序
4.Map接口是键值对象,与Collection没有关系,不是Collection的子接口
5.Set,LIst,Map可以看做集合的三大类
Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素可以根据元素本身访问(也是集合元素不允许重复的原因) 主要的实现类有HashSet和TreeSet
HashSet依赖于HashMap TreeSet依赖于TreeMap
List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引访问。
Map集合中保存Key—Value对形式的元素,访问时根据key值来得到value值
6.Iterator是遍历集合的工具,遍历集合的方式我们主要用迭代器iterator来,
我们说Collection依赖于Iterator,是因为Collection的实现类要实现iterator方法。
LInkIterator是专门为遍历list存在的。
7.Arrays和Collection是工具类,是用来操作数组和集合的

1.LIst

在这里插入图片描述
说明:List接口继承Collection接口,它可以定义一个允许重复的有序集合,通过索引来访问List中的元素,实现类有LinkedList,ArrayList,Vector,Stack。
(1)ArrayList 是一个动态的集合 是我们常用的集合方式,可以存放null值,
每一个ArrayList都有一个初始容量(10),该容量代表了数组的大小,但是随着容器中的元素不断添加,容器的大小也会添加。也正是因为底层是一个数组,所以它的查询效率相比LinkedList快。Array List是非同步的
使用集合存储String类型

package cn.gok.tech01;
import java.util.ArrayList;
import java.util.Collection;
/**
 * Collection常用的方法
 * @author 杨潮
 *
 */
public class TestString {
public static void main(String[] args) {
	//多态
	Collection collection=new ArrayList<>();
	//add添加方法
	collection.add("jQuery");
	collection.add("ajax");
	collection.add("json");
	//获取元素的个数 size()是集合的长度
	System.out.println(collection.size());//3
	System.out.println(collection);//[jQuery ajax json]
	//删除指定元素
	collection.remove("ajax");
	System.out.println(collection);//[jQuery,json]
	//遍历方式 将集合转换为数组遍历输出
	Object[] objects = collection.toArray(); 
	for(int i=0;i<objects.length;i++){
		System.out.println(objects[i]);//jQuery json
	}
	//清空集合
	collection.clear();
	//contains 是否包含
	System.out.println(collection.contains("json"));//false
	//isEmpty 是否为空
	System.out.println(collection.isEmpty());//true

}
}

(2)LInkedLIst 是一个双向链表,与ArrayList不同的是,LInkedList不能随机访问,它需要根据链表的形式去执行,在列表中索引的操作将从开头或结尾遍历列表。所以LInkedLIst的插入和删除操作的效率相比ArrayList快。非同步的
(3)Vector 与ArrayList相似,但是Vector是同步的,是线程安全的动态数组,操作也与ArrayList相似
(4)Stack 是继承Vector 实现了一个后进先出的堆栈,Stack提供了五个方法,
基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的元素。
在这里插入图片描述

02Java集合Set篇

Set的特点
Set里面存储的元素不能重复,没有索引,存取顺序不一致。

	public static void test1() {
		 HashSet<String> hs = new HashSet<>();
	        boolean b1 = hs.add("a");
	        boolean b2 = hs.add("a");
	        
	        hs.add("d");
	        hs.add("c");
	        hs.add("b");
	        System.out.println(hs);//[a, b, c, d]
	        System.out.println(b1);//true
	        System.out.println(b2);//false

	        for (String string : hs) {
	            System.out.println(string);//abcd
	        }
	}

存放自定义的对象

     public static void test2() {
         HashSet<Student> hs = new HashSet<>();
         hs.add(new Student("张三", 20));
         hs.add(new Student("张三", 20));
         hs.add(new Student("李四", 22));
         hs.add(new Student("李四", 22));
         hs.add(new Student("李四", 22));

         for (Student p : hs) {
             System.out.println(p);
             /**
              * Student [name=李四, age=22]
              *  Student [name=张三, age=20]
              */
         }
         
     }

注意:在向HashSet中存放自定义类型对象时,一定要重写hashCode和equals方法

LinkedList
特点:他的底层使用了链表的数据结构,因此LinkedHashSet的特点是读取元素的顺序跟存入元素的顺序是一致的,并且元素不能重复

      public static void test3() {
    	  ArrayList<String> list = new ArrayList<>();
          list.add("a");
          list.add("g");
          list.add("a");
          list.add("b");
          list.add("d");
          list.add("b");
          list.add("b");
          list.add("c");
          list.add("c");

          System.out.println(list);//[a, g, a, b, d, b, b, c, c]
          System.out.println("去除重复后:");//去除重复后:
          LinkedHashSet<String> set2 = new LinkedHashSet<>();
          //将list集合中的所有元素添加到set2
          set2.addAll(list);                                    
          list.clear();                                        
          //将去除重复的元素添回到list中
          list.addAll(set2);                                    
          System.out.println(list);//[a, g, b, d, c]
      }

使用TreeSet存储Integer对象
TreeSet的特点是可以对存放进去的元素进行排序

        public static void test4() {
        	  TreeSet<Integer> ts = new TreeSet<>();
              ts.add(3);
              ts.add(3);
              ts.add(3);
              ts.add(1);
              ts.add(1);
              ts.add(5);
              ts.add(2);
              ts.add(4);
              ts.add(2);
              System.out.println(ts); //[1, 2, 3, 4, 5]
        }

TreeSet存储对象类型

public class Person implements Comparable<Person> {

	 private String name;
	    private int age;

	    public Person() {

	    }

	    public Person(String name, int age) {
	        super();
	        this.name = name;
	        this.age = age;
	    }

	    public String getName() {
	        return name;
	    }

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

	    public int getAge() {
	        return age;
	    }

	    public void setAge(int age) {
	        this.age = age;
	    }

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

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

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public int compareTo(Person o) {
        int num = this.name.compareTo(o.getName());
        if(num != 0){
            return num;
        }else{
            //如果姓名排序一样则以age进行排序
            return this.age - o.getAge();
        }
	}
	}

测试

	public static void test5() {
		TreeSet<Person> ts = new TreeSet<>();
		ts.add(new Person("tony", 23));
		ts.add(new Person("paul", 20));
		ts.add(new Person("lucy", 22));
		ts.add(new Person("james", 24));
		ts.add(new Person("lucy", 21));

		System.out.println(ts);
//[Person [name=james, age=24], Person [name=lucy, age=21],
// Person [name=lucy, age=22], Person [name=paul, age=20], Person [name=tony, age=23]]            
	}

compareTo方法的返回值
TreeSet使用了二叉树的数据结构,负数放到左边,正数放到右边。

当compareTo方法返回0的时候,系统会认为两者一致,所以不会向集合中添加元素
当compareTo方法返回正数的时候,系统将元素存储到右边,所以集合存取顺序一致

03Java集合Map篇

Map接口概述
除了Collection之外,常用的集合还有Map接口,里面常用的实现类图如下
在这里插入图片描述
map中的元素是以键-值的方式存在的,通过键可以获取到值,键是不可以重复的,跟地图比较像,通过一个坐标就可以找到具体的位置。

	public static void test6() {
		 Map<Integer,String> map = new HashMap<>();
	        String s1 = map.put(1001, "swag");
	        map.put(1002, "tony");
	        map.put(1003, "jack");
	        String s2 = map.put(1001, "jackson");

	        System.out.println(s1);//null
	        System.out.println(s2);//swag
	        //判断是否包含传入的键
	        System.out.println(map.containsKey(1002));//true
	        //判断是否包含传入的值
	        System.out.println(map.containsValue("jackson"));//true
	        //获取map的大小
	        System.out.println(map.size());//3
	        //将map中的值返回
	        Collection<String> c = map.values();
	        System.out.println(c);//[jackson, tony, jack]
	        System.out.println(map);//{1001=jackson, 1002=tony, 1003=jack}

	        //删除键是1001的数据并且将值返回
	        String s3 = map.remove(1001);
	        System.out.println(s3);//jackson
	   
	}

方式一:Map中的keySet()返回的是一个包含所有键的Set类型的对象,通过键获取值

    public static void test7() {
    	 Map<Integer, String> map = new HashMap<>();
         map.put(1001, "swag");
         map.put(1002, "tony");
         map.put(1003, "jackson");
         map.put(1004, "michael");

         // 通过键获取值
         String s = map.get(1003);
         System.out.println(s);//jackson

         // 获取map中所有的键返回给Set
         Set<Integer> keySet = map.keySet();

         //遍历set获取键,根据键获取值
         Iterator<Integer> iter = keySet.iterator();
         while(iter.hasNext()){
             Integer key = (Integer)iter.next();
             System.out.println("键:" + key + ",值:" + map.get(key));
         }
         
         for(Integer key : map.keySet()) {            
             System.out.println("键:" + key + ",值:" + map.get(key));
         }
         /**
          * 键:1001,值:swag
                               键:1002,值:tony
                                键:1003,值:jackson
                                 键:1004,值:michael
          */
    }

方式二:Map中的键和值被封装成了Entry对象,并存储在Set集合中,通过entrySet()可以获取到这个Set集合。

    public static  void test8() {
    	  Map<Integer, String> map = new HashMap<>();
          map.put(1001, "swag");
          map.put(1002, "tony");
          map.put(1003, "jackson");
          map.put(1004, "michael");

          //键和值被封装成了Entry对象,并存储在Set集合中
          Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
          Iterator<Map.Entry<Integer,String>> it = entrySet.iterator();
          while(it.hasNext()) {
              //获取每一个Entry对象
              Entry<Integer,String> en = it.next();    
              //根据键值对对象获取键
              Integer key = en.getKey();        
              //根据键值对对象获取值
              String value = en.getValue();    
              System.out.println("键:" + key + ",值:" + value);
          }
//          键:1001,值:swag
//          键:1002,值:tony
//          键:1003,值:jackson
//          键:1004,值:michael

          //增强for循环
          for (Entry<Integer, String> en : map.entrySet()) {
              System.out.println("键:" + en.getKey() + ",值:" + en.getValue());
          }

LinkedHashMap
LinkedHashMap的特点:存取顺序一致

    public static void test9() {
        LinkedHashMap<Integer,String> map = new LinkedHashMap<>();
        map.put(1001, "swag");
        map.put(1002, "tony");
        map.put(1003, "jackson");
        map.put(1004, "michael");

        System.out.println(map);
    }

TreeMap
TreeMap的特点:可以对存储的元素进行排序

    public static void test10() {
    	TreeMap<Integer,String> map = new TreeMap<>();
        map.put(1003, "jackson");
        map.put(1004, "michael");
    	map.put(1001, "swag");
        map.put(1002, "tony");
//{1001=swag, 1002=tony, 1003=jackson, 1004=michael}

        System.out.println(map);
    }

HashMap和Hashtable的区别:线程安全性,同步(synchronization),以及速度。
1.Hashtable是JDK1.0版本出现的,是线程安全的,效率低,不可以存储null键和null值
HashMap是JDK1.2版本出现的,可以存储null键和null值

2.HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

3.另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
4. 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
HashMap不能保证随着时间的推移Map中的元素次序是不变的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值