单列集合的特点与使用

 

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

                                                  单列集合
一.集合的分类
Collection     一次存一个对象, 单列集合
  List     可重复, 有索引,有序
   ArrayList  数组实现, 查找快, 线程不安全
   LinkedList  链表实现, 增删快, 线程不安全

Vector   数组实现, 线程安全
  Set      不可重复, 没索引,无序
   HashSet   使用哈希算法去重复, 效率高, 但元素无序
   TreeSet   TreeSet是用排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
   LinkedHashSet HashSet的子类, 原理相同, 除了去重复之外还能保留存储顺序
   
List迭代(遍历)
  a.普通for循环, 使用get()逐个获取
  b.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
  c.增强for循环, 只要可以使用Iterator的类都可以用
  d.Vector集合可以使用Enumeration的hasMoreElements()和nextElement()方法

二.HashSet(LinkedHashSet)

1.HashSet原理


  我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低
  哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
  当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象,如果没有哈希值相同的对象就直接存入集合
如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较
   比较结果为false就存入, true则不存

实例:


  HashSet实例,  在一个集合中定义很多个重复元素,要求定义一个方法将重复元素去掉
  分析:在一个集合中有重复元素,先定义一个新的HashSet集合,然后把List集合中的元素存入Set集合,
   然后在清空原集合,把Set集合中的元素存入原集合就可以了.

package cn.itcast.test;

import java.util.ArrayList;
import java.util.LinkedHashSet;

public class Test1 {

	/**
	 * @param args
	 * 在一个集合中定义很多个重复元素,要求定义一个方法将重复元素去掉
	 */
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<>();
		list.add("a");
		list.add("a");
		list.add("a");
		list.add("b");
		list.add("b");
		list.add("b");
		list.add("c");
		list.add("c");
		list.add("c");
		list.add("c");
		
		System.out.println(list);
		getSingle(list);
		System.out.println(list);
	}

	private static void getSingle(ArrayList<String> list) {
		LinkedHashSet<String> lhs = new LinkedHashSet<>();
		lhs.addAll(list);				//将list集合中所有的元素添加到LinkedHashSet中,重复自动去掉
		list.clear();					//将原集合清空
		list.addAll(lhs);				//将去除重复的结果添加回原集合
	}

}


2.将自定义类的对象存入HashSet去重复
  类中必须重写hashCode()和equals()方法
  hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
  equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储
  
   实例:自定义一个Person类,重写HashCode方法和equals方法.

 

package cn.itcast.bean;

public class Person implements Comparable<Person>{
	private String name;
	private int age;
	public Person() {
		super();
		
	}
	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
	//eclipse重写的equals方法
	public boolean equals(Object obj) {
		//当调用的对象和传入的对象是同一个对象时
		if (this == obj)						
			return true;						
			//返回true
		//如果传入的对象为null,调用对象不为null
		if (obj == null)						
			return false;						//返回false
		//如果调用的字节码对象和传入的字节码对象不是同一个对象
		if (getClass() != obj.getClass())		
			return false;						//返回false
		//将obj强转为Person
		Person other = (Person) obj;			
		//如果调用的年龄不等于传入的年龄
		if (age != other.age)					
			return false;						//返回false
		//如果调用对象的name为null
		if (name == null) {						
			//如果传入的对象的name不为null
			if (other.name != null)				
				return false;					//返回false
		//如果调用对象的name不等于传入对象的name
		} else if (!name.equals(other.name))	
			return false;						//返回false
		//说明name和age一样返回true
		return true;							
	}
	public int compareTo(Person p) {
		int num = this.name.compareTo(p.name);
		return num == 0 ? this.age - p.age : num;
	}	
}


 


3.Set
  a.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
  b.增强for循环, 只要可以使用Iterator的类都可以使用增强for循环

package cn.itcast.set;

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

public class Demo3_Iterator {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HashSet<String> hs = new HashSet<>();
		hs.add("a");
		hs.add("b");
		hs.add("c");
		hs.add("d");
		
		Iterator<String> it = hs.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		
		for(String obj : hs) {
			System.out.println(obj);
		}
	}

}


三.TreeSet

 


1.特点

 


  TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列


2.使用方式


  a.自然顺序(Comparable)
   TreeSet类的add()方法中会把存入的对象提升为Comparable类型
   如果是自定义对象,必须实现 implements Comparable 接口.
   (增加哪个元素,哪个元素调用compareTo方法)
   调用对象的compareTo()方法和集合中的对象比较
   根据compareTo()方法返回的结果进行存储
  自然顺序比较的实例:在一个集合中存储了无序并且重复的字符串,定义一个方法,
     让其有序(字典顺序),而且还不能去除重复

package cn.itcast.test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;

public class Test3 {

	/**
	 * @param args
	 * 
	 */
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<>();
		list.add("b");
		list.add("b");
		list.add("b");
		list.add("a");
		list.add("a");
		list.add("a");
		list.add("c");
		list.add("c");
		list.add("c");
		sort(list);
		System.out.println(list);
	}
	
	public static void sort(ArrayList<String> list) {//给TreeSet集合的构造函数传入比较器,比较器就是Comparator的子类对象	
		TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {	
			@Override
			//重写Comparator中的compare方法
			public int compare(String s1, String s2) {					
				//主要条件按照字典顺序比较
				//如果两个比较的字符串一样,就会返回0,返回0就不会存储在TreeSet集合中
				int num = s1.compareTo(s2);								
			//所以如果比较的结果是0就返回一个非0的数字就可以将重复的保留
				return num == 0 ? 1 : num;								
			}															
		});
		
		//将list集合中的所有元素添加到ts中,排序保留重复
		ts.addAll(list);						
		//将list清空
		list.clear();							
		//将ts中排序后的结果存储在list集合中
		list.addAll(ts);						
	}

b.比较器顺序(Comparator)
   创建TreeSet的时候可以制定 一个Comparator
   一般用匿名内部类:
    new Comparator(){
     public void compare(T s1, T s2){
      int num = s1.compareTo(s2)
     }
    }
   如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
   add()方法内部会自动调用Comparator接口中compare()方法排序
   使用比较器的实例:
     * 请输入学生考试成绩:
     * 张三,80,80,80
     * 李四,70,75,65
     * 王五,90,95,80
     * 赵六,60,60,60
     * quit
     *
     * 排序后的学生信息:
     * 王五,90,95,80,265
     * 张三,80,80,80,240
     * 李四,70,75,65,210
     * 赵六,60,60,60,180
   分析:先定义一个Student类,使用匿名内部类,把比较器传入TreeSet的构造函数.


package cn.itcast.test;

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class Compare { 
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入学生成绩,格式是 姓名,数学成绩,语文成绩,英语成绩");
		TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
			@Override
			public int compare(Student s1, Student s2) {
				int num = s2.getSum() - s1.getSum();
				return num == 0 ? 1 : num;
			}
		});
		
		while(true) {
			String line = sc.nextLine();
			if("quit".equals(line))
				break;
			String[] arr = line.split(",");
			int math = Integer.parseInt(arr[1]);
			int chinese = Integer.parseInt(arr[2]);
			int english = Integer.parseInt(arr[3]);
			ts.add(new Student(arr[0], math, chinese, english));
		}
		
		System.out.println("排序后的学生信息:");
		
		for (Student student : ts) {
			System.out.println(student);
		}
	}

}


c.两种方式的区别
   TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
   TreeSet如果传入Comparator, 就优先按照Comparator的顺序进行比较.

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值