Java - 集合

Java集合框架位于java.util包中,提供了一套性能优良、使用方便的接口和类。Java集合框架共有三大类接口: List、Set、Map:

虚线框:接口,实线框:实现类

 List接口:

概念:一组对象的集合,容器,用来存储对象的,他解决了数组一旦声明长度就固定的这种局限。List 接口存储一组不唯一,有序(插入顺序)的对象。

分类:集合分为两大类,用接口来体现

  • 两大接口Collection和Map,其中Collection接口下面还有list接口和map接口

List接口特点:存储有顺序、不唯一的对象

List接口常用实现类:Vector、Arraylist、LinkedList

1、Arraylist:底层是数组实现,是长度可变的动态数组,观察源码可发现当创建一个ArrayList对象时,其实就相当于new了一个长度为10的Object类型的数组,当加入新的元素的时候,数组长度变为:原来长度*3/2+1,ArrayList中元素有序、通过角标操作,从0开始,ArrayList遍历元素和随机访问元素的效率比较高(角标),插入、删除等操作频繁时性能低下。ArrayList类实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高。

常用方法包括:size(集合长度)、add(添加元素)、get(通过角标获得元素)、set(给指定角标添加元素)、remove(删除元素)

2、LinkedList:底层是链表实现,LinkedList类采用链表存储方式。插入、删除元素时效率比较高,查找效率较低。插入、删除操作频繁时,可使用LinkedList来提高效率,LinkedList额外提供对头部和尾部元素进行添加和删除操作的方法。

常用方法包括:addFirst、removeFirst、addLast、removeLast

3、Vector:底层也是基于数组实现

三个实现类的区别:

  • Arraylist和LinkedList线程不同步:效率高
  • Vector是线程安全的,用synchronized修饰的。效率低

ArrayListLinkedList的使用场景:

ArrayList:

  • 遍历元素和随机访问元素的效率比较高
  • 插入、删除等操作频繁时性能低下

LinkedList:

  • 插入、删除元素时效率较高
  • 查找效率较低

集合遍历的集中方式:

  • 1、普通for循环
  • 2、增强for循环forEach
  • 3、Iterator(迭代器) 中的hasnext() 和 next()方法
  • 注意:迭代器是专门为集合而生,它存在的意义就是遍历集合,在迭代器中,一边遍历一边移除的时候,一定要用迭代器的remove()。

关于哈希算法:

http://www.cnblogs.com/jiewei915/archive/2010/08/09/1796042.html

https://www.cnblogs.com/dolphin0520/p/3681042.html

package com.liudm.demo12;

import java.util.ArrayList;
import java.util.List;

public class ListDemo {
	public static void main(String[] args) {
		//容器——数组
		//集合存储的都是对象
		List list = new ArrayList();  //底层:new了一个长度为10的object类型的数组
		//ArrayList:长度可变组,遍历效率高
		//数据加入是有序的,可重复
		list.add(12);  //12:int→Integer:基本数据和包装类自动转化
		list.add("abc");
		list.add("abca");
		list.add(45.5f);
		
		System.out.println(list.get(1));  //角标从零开始
		System.out.println(list.size());   //数组:length,字符串:length()
		
		System.out.println(list.remove(1)); //根据角标移除
		list.remove("abca");  //根据内容移除
		
		Integer n = 12;
		list.remove(n);   //根据内容移除
		
		System.out.println(list);
		
		System.out.println(list.isEmpty());
		System.out.println(list.set(0, 22));  //更新
		list.clear();  //清空,没有返回值,不能打印
		
		System.out.println(list);  //
	}
}

 

package com.liudm.demo12;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListDemo1 {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add(12);
		list.add("abc");
		list.add("abca");
		list.add(45.5f);
		
//		for (int i = 0; i < list.size(); i++) {   //一种遍历
//			System.out.println(list.get(i));
//		}
//		for (Object o : list) {   //一种遍历
//			System.out.println(o);
//		}
		
		//迭代器,判断是否有下一个元素
		Iterator it = list.iterator();
		while (it.hasNext()) {
			Object o = it.next();
			System.out.println(o);
		}
	}
}

package com.liudm.demo12;

import java.util.LinkedList;

public class ListDemo2 {
	public static void main(String[] args) {
		//linkedlist:删除、添加效率高,便于查找
		//链表查找,3和length比较,大于就在后面找,小就在前面找
		LinkedList list = new LinkedList();
		list.add(34);   //
		list.addFirst("12");
		list.add(34);
		list.addFirst("12");
		list.add(34);
		list.addFirst("12");
		
		System.out.println(list.get(3));   //
	}
}

实验:定义一个List对象,如下:

List <String>list = new ArrayList<String>();

在list中添加元素,java,linux,hadoop,hive

在list的第二个位置添加元素,mysql

用Iterator迭代器遍历打印list中元素

在打印时,将list中的mysql,修改为hbase

package com.liudm.demo12;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListTest {
	public static void main(String[] args) {
		List <String> list = new ArrayList<String>();
		list.add("java");
		list.add("linux");
		list.add("hadoop");
		list.add("hive");
		
		list.add(1, "mysql");
		
		Iterator it = list.iterator();
		while (it.hasNext()) {
			Object object = it.next();
			if ("mysql".equals(object)) {
				object = "hbase";
			}
			System.out.println(object);
		}
	}
}

 

参考源码:

package my.list;  
import java.util.ArrayList;  
import java.util.Iterator;  
import java.util.List;  
public class ListDemo {  
    public static void main(String[] args) {  
        List <String>list = new ArrayList<String>();  
	    //在list中添加元素,java,linux,hadoop,hive  
	    list.add("java");  
	    list.add("linux");  
	    list.add("hadoop");  
	    list.add("hive");  
	    
	    //在list的第二个位置添加元素,mysql  
	    list.add(1,"mysql");//因为集合角标从0开始,所以第二位置的角标是1  
	    //查看集合长度  
	    System.out.println(list.size());  
	    //通过角标查看元素  
	    System.out.println(list.get(2));  
	    //遍历集合-普通for循环  
	    for (int i = 0; i < list.size(); i++) {  
	    	System.out.println(list.get(i));  
	    }  

	    //遍历集合-增强for循环  
	    for (String str : list) {  
	    	System.out.println(str);  
	    }  
	  
	    //迭代器  
	    Iterator  it = list.iterator();  
	    while(it.hasNext()){   //判断是否有下一个元素  
		    String o =  (String) it.next();    //接收下一个元素  
		    if(o.equals("mysql")){  
		    	o = "hbase";  
		    }  
		    System.out.print(o + "   ");  
	    }  
    }  
}

 


练习1:定义一个List对象,如下
List <String>list = new ArrayList<String>();
在list中添加元素,nihao,wohao,dajiahao,nihao
在list的第二个位置添加元素,tahao
用Iterator迭代器遍历打印list中元素
在打印时,将list中的nihao,修改为nibuhao

package com.liudm.demo12;

import java.util.ArrayList;
import java.util.Iterator; 
import java.util.List;

public class Test1 {
	public static void main(String[] args) {  
        List <String>list = new ArrayList<String>();  
	    list.add("nihao");  
	    list.add("wohao");  
	    list.add("dajiahao");  
	    list.add("nihao");  
	    
	    list.add(1,"tahao");
	  
	    //迭代器  
	    Iterator <String> it =  list.iterator();

	    while(it.hasNext()){
		    Object o =  it.next();
		    if(o.equals("nihao")){  
		    	o = "nibuhao";  
		    }  
		    System.out.println(o + "   ");  
	    }  
    }  
}

 

练习2:选择一个集合添加三个Person对象,把姓名相同和年龄的的人当做同一个人,禁止重复添加。
提示:
Person类中定义name和age属性,重写hashCode()方法和equals()方法,针对Person类的name和age属性进行比较,如果name相同,hashCode()方法的返回值相同,equals方法返回true。

Person类:

package com.liudm.demo12;

public class Person {
	private String name;
	private int age;
	
	public int hashCode(){
		return name.hashCode();
	}
	public boolean equals(Object object){
		if (this == object) {
			return true;
		}
		if (object == null) {
			return false;
		}
		Person oth = (Person) object;
		return oth.name.equals(this.name);
	}
	
	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;
	}
}

测试类:

package com.liudm.demo12;

import java.util.HashSet;

public class Test2 {
	public static void main(String[] args) {
		HashSet person = new HashSet();
		
		Person p1 = new Person("Jobs",40);
		Person p2 = new Person("Marry",25);
		Person p3 = new Person("Jobs",41);
		person.add(p1);
		person.add(p2);
		person.add(p3);
		
		for (Object object : person) {
			Person per = (Person) object;
			System.out.println(per.getName() + "  " + per.getAge());
		}
		
		person.clear();  //清空,做下一个测试
		System.out.println();
		
		Person pe1 = new Person("Jobs",40);
		Person pe2 = new Person("Marry",25);
		Person pe3 = new Person("Job",40);
		person.add(pe1);
		person.add(pe2);
		person.add(pe3);
		
		for (Object obj : person) {
			Person pers = (Person) obj;
			System.out.println(pers.getName() + "  " + pers.getAge());
		}
	}
}

 

练习3:使用对象保存每个学员的信息,包括学号、姓名、三门课的成绩、平均成绩,使用集合存所有学员的信息,需要实现以下函数:

  •    单个学员信息的录入;
  •     显示所有学员信息;
  •     排序;(按照平均成绩由大到小)
  •     插入;(插入后保持有序)
  •     删除;(删除后保持有序)

在主方法中调用以上函数,分别完成录入、排序、插入和删除功能,并显示排序前后的学员信息,以及插入删除后的学员信息


set接口:

Set接口存储一组唯一,无序的对象。无get()方法,无法使用普通for循环遍历,可以使用增强for循环或使用Iterator遍历。

Set接口——HashSet

  • HashSet Set接口常用的实现类
  • HashSet允许集合元素值为null
  • HashSet不是同步的,如果多个线程同时访问,则必须通过代码来保证其同步
  • 操作数据的方法与List类似,Set接口不存在get()方法
HashSet  newsTitleSet = new HashSet();
NewTitle car = new NewTitle(1, "汽车", "管理员");
//增加元素
newsTitleSet.add(car);

//遍历集合
for(Object obj :newsTitleList){
    NewTitle title=(NewTitle)obj;
	System.out.println(title.getTitleName());
}

HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找功能。

HashSet中存储元素,HashSet会调用该对象的hashcode()方法来得到HashCode值,然后根据HashCode值决定改对象在HashSet中的存储位置。

HashSet中比较元素相等规则:

  • equals比较相等
  • hashCode()返回的值相等

 注意:个对象通过equals方法比较相等,HashCode比较不相等,则仍然能添加成功。

Set接口——TreeSet

TreeSet可以保证集合中的元素处于排序状态。

TreeSet支持两种排序方法

  • 自然排序(ASCII码)
  • 定制排序
public static void main(String{} args) {
    //测试一下数字
    TreeSet<Integer> set = new TreeSet<Integer>();
    //反向存储数据
    for(int i = 10; i >= 1; i--){
        set.add(i);
    }
    //如果add了相同的数据,是无效的,因为set集合不能重复元素
    set.add(10);
    //输出结果,可以看到数据为自然的数字排序
    System.out.println(set);
    //输出结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}

EG:

注意:遍历的时候,先遍历左子树,然后遍历右子数
TreeSet ts =new TreeSet();  
ts.add(new Student("lisi02", 22));  
ts.add(new Student("lisi007", 20)); 
ts.add(new Student("lisi09", 19));  
ts.add(new Student("lisi11", 40));  
ts.add(new Student("lisi16", 30));  
ts.add(new Student("lisi16", 50)); 
ts.add(new Student("lisi16", 23)); 

TreeSet定制排序两种方式

1.实现comparable

  • 类上implement Comparable
  • 重写compareTo()方法:在方法内定义比较算法, 根据大小关系, 返回正数负数或

2.传入一个比较器(实现comparator

注意:使用TreeSet存储对象的时候, add()方法内部就会自动调用compareTo()方法进行比较, 根据比较结果使用二叉树形式进行存储。

Iterator接口:

Iterator接口表示对集合进行迭代的迭代器,专门实现集合的遍历。

方法:

  • hasNext():判断是否存在另一个可访问的元素
  • next():返回要访问的下一个元素
System.out.println("使用Iterator遍历,分别是:");
Iterator it = list.iterator();
while (it.hasNext()) {         //当有元素时返回true
    String name = (String)it.next();     //返回类型是Object
    System.out.println(name);
}

map接口:

1、Java 中的 Map 接口 是和 Collection 接口 同一等级的集合根接口,它 表示一个键值对 (key-value) 的映射,我们通常使用接口的实现类来存储元素。Map的常用实现类如下图所示:

HashMap:是Map接口最常用的实现类。HashMap中的键不能重复,如果重复,键对应的值被覆盖了;HashMap中的键和值都可以为null;键如果不存在,拿到的是一个null;不支持线程同步,当有多个线程同时写HashMap,可能导致数据不一致,可以使用Collection的synchronizedMap方法使其同步

LinkedHashMap:LinkedHashMap内部是双向链表结构,这种数据结构保证了元素插入的顺序,支持线程同步。

TreeMap:TreeMap 是一个有序的key-value集合,它是基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。此外,TreeMap是非线程同步的。

2、Map 接口提供了三种角度来分析 Map:

  • KeySet
  • Values
  • Entry

(1).KeySet

KeySet 是一个 Map 中键(key)的集合,可以通过 Map.keySet() 方法获得,以 Set 的形式保存,不允许重复,因此键存储的对象需要重写 equals() 和 hashCode() 方法。

(2).Values

Values 是一个 Map 中值 (value) 的集合,通过 Map.values() 方法获得,以 Collection 的形式保存,因此可以重复。

(3).Entry

Entry 是 Map 接口中的静态内部接口,表示一个键值对的映射,通过 Map.entrySet() 方法获得的是一组 Entry 的集合,保存在 Set 中,所以 Map 中的 Entry 也不能重复。

Entry 具有的方法:

getKey() , 获取这组映射中的键 key

getValue() , 获取这组映射中的值 value

setValue() , 修改这组映射中的值

hashCode() , 返回这个 Entry 的哈希值

equals() , 对比 key-value 是否相等

package com.liudm.demo12;

import java.util.Collection;
import java.util.HashMap;
import java.util.Set;

//map:键值对
public class mapDemo {
	public static void main(String[] args) {
		HashMap map = new HashMap();
		
		//map.put(key, value)
		map.put("班长","张三");
		map.put("班长1","张三1");
		map.put("班长2","张三2");
		map.put("班长2","张三22");
		map.put(null,"张三");   //可以为null
		
		System.out.println(map.get("班长2"));
		System.out.println();
		
		Set s = map.keySet();   //hashmap的key:HashSet
		for (Object object : s) {
			System.out.println(object);
		}
		System.out.println();
		
		//map.values();
		Collection values = map.values();
		for (Object object : values) {
			System.out.println(object);
		}
	}
	
}

package com.liudm.demo12;

import java.util.ArrayList;
import java.util.List;

public class DemoT {
	public static void main(String[] args) {
		int [] nus = {1,2,3};
		
		//<> :泛型,集合泛型
		List<String> list = new ArrayList<String>();
		list.add("aa");
		//list.add(123);
		list.add("123");
	}
}

 练习:Map接口和HashMap练习
定义一个Map对象,如下
Map<String,String> map = newHashMap<String,String>();
在map中添加键值对(“1”,“xiaohong”)、(“2”,”xiaowang”)、(“3”,”xiaoli”)
将map中的键值对打印出来(提示:可以将key集合放到一个set中,定义Iterator遍历器取出set中的key,然后通过key的值在map中取出对应value值,并将这两个值打印出来)

package com.liudm.demo12;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Test4 {
	public static void main(String[] args) {
		//Map需要导包
		Map<String, String> map = new HashMap<String, String>();
		map.put("1", "xiaohong");
		map.put("2", "xiaowang");
		map.put("3", "xiaoli");

		Set set = map.keySet();   //Set需要导包
		Iterator it = set.iterator();   //Iterator需要导包
		while (it.hasNext()) {
			Object obj = it.next();
			Object object = map.get(obj);
			System.out.println("key:" + obj + "  value:" + object);
		}
	}
}

 

 实验:完成map集合的数据存储和遍历

package com.liudm.demo12;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class mapTest {
	public static void main(String[] args) {
		//Map需要导包
		Map<String, String> map = new HashMap<String, String>();
		map.put("NO.1", "第一名");
		map.put("NO.2", "第二名");
		map.put("NO.3", "第三名");
		map.put("NO.4", "第四名");
		map.put(null, null);
		map.put(null, null);  //两个null只会输出一个
		
		Set set = map.keySet();   //Set需要导包
		Iterator it = set.iterator();   //Iterator需要导包
		while (it.hasNext()) {
			Object obj = it.next();
			Object object = map.get(obj);
			System.out.println("key:" + obj + "  value:" + object);
		}
	}
}

参考源码:

package my.map;  
import java.util.Collection;  
import java.util.HashMap;  
import java.util.Iterator;  
import java.util.Map;  
import java.util.Map.Entry;  
import java.util.Set;  
public class MapDemo {  
    public static void main(String[] args) {  
        Map<String,String> map=new HashMap<String, String>();  
        //使用put添加元素  
        map.put("first","张三");  
        map.put("second","李四");  
        map.put("third","王五");  
        map.put("fourth","赵六");  
        map.put("fifth","李明");  
        //存放两个key-value为空的元素,打印时出现一个  
        map.put(null, null);  
        map.put(null, null);  
  
        //方式1.使用 keySet  
         Set set = map.keySet();// map中的键其实就是一个set集合  
         Iterator it = set.iterator();  
         while (it.hasNext()) {  
             Object str = it.next();// 键  
             Object object = map.get(str);// 值  
             System.out.println("键 : "+str + "  值:" + object);  
         }

         //方式2:使用entrySet  
         Set set1 = map.entrySet();  
         Iterator it1 = set.iterator();  
         while (it.hasNext()) {  
            Entry entry = (Entry) it.next();// 键+值  
            Object key = entry.getKey();  
            Object value = entry.getValue();// 真正的值  
            System.out.println(key + "--->" + value);  
         }  
    }  
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值