Java进阶3(Set集合)


集合概念:对象的容器,实现了对对象常用的操作,类似于数组功能
数组和集合的区别

  1. 数组长度固定,集合长度不固定。
  2. 数组可以存储基本类型和引用类型,集合只能存储引用类型(或者基本类型的装箱操作)

Collection父接口

特点:代表一组任意类型的对象,无序、无下标、不能重复

方法
boolean add(Object obj) //添加一个对象。
boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中
void clear() //清空此集合中的所有对象。
boolean contains(Object o) //检查此集合中是否包含o对象
boolean equals(Object o) //比较此集合是否与指定对象相等
boolean isEmpty() //判断此集合是否为空
boolean remove(Object o) //在此集合中移除o对象
int size() //返回此集合中的元素个数
Object[] toArray() //将此集合转换成数组。

在这里插入图片描述

类型存储结构是否有序
ArrayList数组结构
LinkedList链表结构
Vector数组结构
HashSet哈希表(数组+链表+红黑树)
TreeSet排序二叉树是(要实现compare接口)
HashMap哈希表(数组+链表+红黑树)
TreeMap近似平衡的二叉树是(要实现compare接口)

List子接口

方法
void add(int index, Object o) //在index位置插入对象o
boolean addAll(int index, Collection c) //将一个集合中的元素添加到此集合中的index位置
Object get(int index) //返回集合中指定位置的元素
List subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之间的元素(含头不含尾)

ListIterator要比Iterator好用,它可以向前或向后遍历,添加删除修改元素

//list的遍历
//3.1使用for遍历
System.out.println("----------------使用for遍历------------");
for(int i = 0; i < list.size(); i++) System.out.println(list.get(i));
//3.2使用增强for
System.out.println("-----------使用增强for--------------------");
for (Object object : list) System.out.println(object);
//3.3使用迭代器
System.out.println("-----------使用迭代器---------------------");
Iterator it = list.iterator();
while(it.hasNext()) System.out.println(it.next());
//3.4使用列表迭代器
ListIterator lit = list.listIterator();
System.out.println("-----------使用列表迭代器从前往后-----------------");
while(lit.hasNext()) System.out.println(lit.nextIndex() + ":" + lit.next());
System.out.println("-----------使用列表迭代器从后往前-----------------");
while(lit.hasPrevious()) System.out.println(lit.previousIndex() + ":" + lit.previous());

在list中存储的都是封装类,所以删除的时候要用list.remove(new Integer(10));

ArrayList[重点]

  • 数组结构实现,查询遍历快,增删慢
  • JDK1.2版本,运行效率快,线程不安全

源码分析
DEFAULT_CAPACITY = 10 默认容量大小
注意:如果没用向集合中添加任何元素,容量是0;添加一个元素后,容量是10
每次扩容原来的1.5倍
elementData 存放元素的数组
size 实际元素个数
add添加元素

Vector

  • 数组结构实现,查询快,增删慢
  • JDK1.0版本,运行效率慢,线程安全
//使用枚举器循环
Enumeration en = v1.elements();
while(en.hasMoreElements()) {
	String o = (String)en.nextElement();
	System.out.println(o);
}
//其他方法:v1.firstElement();v1.lastElement();v1.elementAt(0);

LinkedList

  • 链表结构实现,查询慢,增删快
泛型集合

概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
特点:

  • 编译时即可检查,而非运行时抛出异常
  • 访问时,不必类型转换(拆箱)
  • 不同泛型之间引用不能相互赋值,泛型不存在多态

Set子接口

Set中不能用普通for循环因为里面没有根据下标取某个元素的方法
有一个LinkedHashSet,有序

HashSet/Treeset

HashSet存储过程:

  1. 根据hashcode计算保存的位置,如果位置为空,直接保存,否则执行第二步
  2. 再执行equals方法,如果equals方法为true,则认为是重复,否则形成链表
getClass()
  • public final Class<?> getClass()
  • 返回引用存储的实际对象类型
  • 判断两个引用中实际存储对象类型是否一致
hashCode()
  • 返回该对象的哈希码值
  • 哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值
  • 相同对象返回相同哈希码
toString()
  • 返回该对象的字符串表示(表现形式)
  • 可以根据程序需求覆盖该方法@override
equals()
  • public boolean equals(Object obj)
  • 默认实现为(this == obj),比较两个对象地址是否相同
  • 可进行覆盖,比较两个对象的内容是否相同
finalize()
  • 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
  • 垃圾对象:没有有效引用指向此对象时,为垃圾对象
  • 垃圾回收:由GC销毁垃圾对象,释放数据存储空间
  • 自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
  • 手动回收机制:使用System.gc();通知JVM执行垃圾回收
例子
package cn.edu.tyut.demo.map;

public class Person implements Comparable<Person> {
	//继承了Comparable接口,可以用来比较
	private String name;
	private int 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;
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int compareTo(Person o) {
		return this.age - o.age;
	}
	//重写compareTo函数,让comparable比较是根据age来进行的
	
	@Override
	public boolean equals(Object obj) {
		//1判断两个对象是否是同一个引用
		if(this == obj)
			return true;
		//2判断obj是否为null
		if(obj == null)
			return false;
		//3判断是否为同一个类型
		if(obj instanceof Person) {
		//4强制类型转换
		Person p = (Person)obj;
		//5比较属性
		if(this.getName() == p.getName() && this.age == p.age)
				return true;
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		return (name + age).hashCode();
	}
	//让equals和hashCode判等是根据name和age来判断的
	@Override
	protected void finalize() throws Throwable {
		System.out.println(this.name + "对象被回收了");
	}
}
package cn.edu.tyut.demo.map;

import java.util.HashSet;
import java.util.Iterator;
import java.util.TreeSet;

import org.junit.Test;

public class SetTest {
	@Test
	public void fun1() {
		HashSet<Person> set = new HashSet<Person>();
		Person p1 = new Person("zhangsan", 16);
		Person p2 = new Person("zhangsan", 16);
		Person p3 = new Person("zhangsan", 16);
		
		set.add(p1);
		set.add(p2);
		set.add(p3);
		set.add(p3);//这个元素和前面以及放进去的元素重复了
		//遍历方法
		//1、普通的for循环不能用了
		//2、增强
		for (Person person : set) System.out.println(person);
		//3、迭代器
		//hasNext();有下一个元素
		//next();获取下一个元素
		//remove();删除当前元素
		Iterator it = set.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}
	//Person [name=zhangsan, age=16]
	//Person [name=zhangsan, age=16]
	@Test
	//TreeSet
	public void fun2() {
		TreeSet<Person> set = new TreeSet<Person>();
		Person p1 = new Person("zhangsan",25);
		Person p2 = new Person("wangwu",16);
		Person p3 = new Person("lisi",17);

		set.add(p1);
		set.add(p2);
		set.add(p3);
		for (Person person : set) {
			System.out.println(person);
		}
		Iterator<Person> it = set.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}
	//Person [name=wangwu, age=16]
	//Person [name=lisi, age=17]
	//Person [name=zhangsan, age=25]
	@Test 
	public void fun3() {
		//Comparator:实现定制比较(比较器)
		//Comparable:可比较的
		//创建集合,用匿名内部类表示比较规则
		TreeSet<Person> set = new TreeSet<Person>(new Comparator<Person>() {
			//先比较年龄,在比较名字
			//使用匿名内部类就不用在Person中实现comparable接口了
			@Override
			public int compare(Person o1, Person o2) {
				int n1 = o1.getAge() - o2.getAge();
				int n2 = o1.getName().compareTo(o2.getName());//字符串中已经实现了compareTo
				return n1 == 0 ? n2 : n1;
			}
		});
		Person p1 = new Person("zhangsan",25);
		Person p2 = new Person("wangwu",16);
		Person p3 = new Person("lisi",17);
		set.add(p1);
		set.add(p2);
		set.add(p3);
		System.out.println(set.toString());
		//[Person [name=wangwu, age=16], Person [name=lisi, age=17], Person [name=zhangsan, age=25]]
	}
	@Test
	public void fun4() {
		Person p1 = new Person("aaa", 34);
		new Person("laji", 4);
		p1 = new Person("bbb", 45);
		System.gc();
		System.out.println("回收垃圾");
	}
	//回收垃圾
	//aaa对象被回收了
	//laji对象被回收了
}

Map接口

Map接口的特点

  1. 用于存储任意键值对(Key-Value)
  2. 键:无序、无下标、不允许重复(唯一)
  3. 值:无序、无下标、允许重复
    用remove删除的时候只需要写键的名称
    录入键相同的元素,后录入的值会把前一个值代替
    在这里插入图片描述

HashMap/TreeMap

JDK1.2版本,线程不安全,运行效率快,允许用null作为key或是value
默认容量是16,使用key的equals和hashcode作为重复依据

package cn.edu.tyut.demo.map;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;

import org.junit.Test;

public class MapTest {
	@Test
	public void fun() {
		HashMap<String, Person> map = new HashMap<String, Person>();
		map.put("1", new Person("zhangsan", 25));
		map.put("2", new Person("Lisi", 25));
		//map.put("3", new Person("8D", 80));
		map.put(null, null);
		//遍历map
		//1、得到key的集合(使用keySet)
		System.out.println("---------keySet----------");
		//Set<String> keyset = map.keySet();
		for (String string : map.keySet()) {
			System.out.println(string);
		}
		//2、使用entrySet()方法(效率高)
		System.out.println("---------entrySet--------");
		//Set<Entry<String, Person>> entries = map.entrySet();
		for (Entry<String, Person> entry : map.entrySet()) {
			System.out.println(entry);
			System.out.println(entry.getKey() + "-------" + entry.getValue());
		}
	}
//	---------keySet----------
//	null
//	1
//	2
//	---------entrySet--------
//	null=null
//	null-------null
//	1=Person [name=zhangsan, age=25]
//	1-------Person [name=zhangsan, age=25]
//	2=Person [name=Lisi, age=25]
//	2-------Person [name=Lisi, age=25]
	@Test
	public void fun2() {
		TreeMap<Person, String> map = new TreeMap<Person, String>();
		map.put(new Person("fff", 25), "2");
		map.put(new Person("tttt", 45), "5");
		map.put(new Person("zhangsa", 12), "3");
		System.out.println(map);
		System.out.println("-------keySet()--------");
		for(Person key : map.keySet()) {
			System.out.println(key);
		}
		System.out.println("------entrySet()-------");
		for(Entry<Person, String> entry : map.entrySet()) {
			System.out.println(entry.getKey() + "--------" + entry.getValue());
		}
	}
//	{Person [name=zhangsa, age=12]=3, Person [name=fff, age=25]=2, Person [name=tttt, age=45]=5}
//	-------keySet()--------
//	Person [name=zhangsa, age=12]
//	Person [name=fff, age=25]
//	Person [name=tttt, age=45]
//	------entrySet()-------
//	Person [name=zhangsa, age=12]--------3
//	Person [name=fff, age=25]--------2
//	Person [name=tttt, age=45]--------5
	@Test
	public void fun3() throws IOException {
		Properties prop = new Properties();
		prop.load(this.getClass().getClassLoader().getResourceAsStream("config.properties"));
		String value = (String)prop.get("password");
		System.out.println(value);
	}
	//12345
}
//config.properties
username=zhangsan
password=12345

Properties

Hashtable : JDK1.0版本,线程安全,运行效率慢,不允许null作为key或是value
Hashtable的子类Properties,要求key和value都是String。通常用于配置文件的读取

Collections方法

@Test
public void fun7() {
	//Collections工具类
	List<Integer> list = new ArrayList<Integer>();
	list.add(4);
	list.add(-1);
	list.add(89);
	list.add(12);
	
	System.out.println("排序前" + list);
	//sort排序
	Collections.sort(list);
	System.out.println("排序后" + list);
	//binarySearch二分查找
	int a = Collections.binarySearch(list, -1);
	System.out.println("所查找的元素位置是:" + a);
	//copy复制,必须保证目标数组比原始数组长
	List<Integer> dest = new ArrayList<Integer>();
	for(int i = 0; i < list.size(); i++) {
		dest.add(0);
	}
	dest.add(0);
	Collections.copy(dest, list);
	System.out.println("被复制的目标数组是" + dest);
	//reverse反转
	Collections.reverse(list);
	System.out.println("反转后" + list);
	//shuffle打乱
	Collections.shuffle(list);
	System.out.println("打乱后" + list);//每次打乱后list都可能不一样
	
	//list转成数组
	Integer[] arr = list.toArray(new Integer[0]);//arr的长度肯定比后面的0大,就是list的长度
	System.out.println(Arrays.toString(arr));
	
	//把基本类型转为数组时最好用包装类,不然要用到List<int[]>
	//数组转成集合
	String[] names = {"张三", "李四", "王五"};
	//集合是一个受限集合,不能添加和删除
	List<String> list2 = Arrays.asList(names);
	System.out.println("数组转成的集合是" + list2);
}
//排序前[4, -1, 89, 12]
//排序后[-1, 4, 12, 89]
//所查找的元素位置是:0
//被复制的目标数组是[-1, 4, 12, 89, 0]
//反转后[89, 12, 4, -1]
//打乱后[4, 12, -1, 89]
//[4, 12, -1, 89]
//数组转成的集合是[张三, 李四, 王五]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值