最近一直在看Java里的集合这块,初看觉得内容不多,细看之后发现东西真的很多。我的学习也还只是停留在初级阶段,这边我想做一个大概的整理。
这个是集合的大致分类,我只学习了一般用到的一些集合,其他更详细的暂时还没有学习。
首先,以下的程序基本上都用到了这个Student类,所以放在最上面贴出来。
package hashmap20160107;
public class Student /*implements Comparable<Student>*/{
private String name;
private Integer age;
Student(String name, Integer age){
this.setName(name);
this.setAge(age);
};
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public Integer getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
/*public int compareTo(Student arg0) {
return this.getAge().compareTo(arg0.getAge());
//这边返回的是一个int型的数据
}
public boolean equals(Object o){
if(this == o){
return true;
}
if(! (o instanceof Student)){
return false;
}
final Student other = (Student)o;
if(this.name.equals(other.getName()) && this.age.equals(other.getAge())){
return true;
}
else{
return false;
}
}
public int hashCode(){
int result;
result = (name == null?0:name.hashCode());
result = 37*result + (age == null?0:age.hashCode());
return result;
}
*/
}
这边因为下面的集合有的要实现comparable接口,有的要重写equals和hashcode方法,所以都放了进去。
1、ArrayList(按顺序存储可重复)
这个程序没有用到实体类里的任何方法
package Arraylist20151203;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
/**
*
* http://jingyan.baidu.com/article/5bbb5a1b1f4c7613eba1790d.html 百度经验
*
*/
public class test2 {
public void run(){//整形数组
ArrayList<int[]> list = new ArrayList<int[]>();
int[] nums = {0,1,2,3,4};
list.add(nums);
Iterator<int[]> iterators = list.iterator();
//循环迭代器
while (iterators.hasNext()) { //如果有下一个值,进入循环
int[] result = iterators.next(); //得到迭代器中下一个值 返回String类型
for(int i = 0;i<result.length;i++){
System.out.println(result[i]);//输出结果
}
}
}
public void run2(){//插入字符串中
ArrayList<String> list2 = new ArrayList<String>();
list2.add("我是第一个对象");
list2.add("我是第二个对象");
list2.add("我是第三个对象");
list2.add("我是第四个对象");
list2.add("我是第五个对象");
list2.add(1,"我是插入的对象");//在第一个对象后面插入
Iterator<String> i = list2.iterator();
while(i.hasNext()){
String s = i.next();
System.out.println(s);
}
}
public void run3(){//全部插入
ArrayList<String> list3 = new ArrayList<String>();
list3.add("我是第一个对象");
list3.add("我是第二个对象");
list3.add("我是第三个对象");
ArrayList<String> list4 = new ArrayList<String>();
list4.add("我是插入的对象");
list4.addAll(list3);//在前面插入
Iterator<String> i = list4.iterator();
while(i.hasNext()){
String s = i.next();
System.out.println(s);
}
}
public void run4(){//全部插入
ArrayList<String> list5 = new ArrayList<String>();
list5.add("我是第一个对象");
list5.add("我是第二个对象");
list5.add("我是第三个对象");
list5.add("我是第四个对象");
ArrayList<String> list6 = new ArrayList<String>();
list6.add("我是第一个对象");
list6.add("我是第二个对象");
/*
* 下面做了增删改三个功能,可以都试一下体会一下
*/
//list5.addAll(0,list6);//可以指定位置插入对象,允许重复
//list5.removeAll(list6);//删除对象
//list5.set(0,"我是改变的对象");//可以改变对象的值
Iterator<String> i = list5.iterator();
while(i.hasNext()){
String s = i.next();
System.out.println("清空之前 "+s);
}
String ele = list5.get(1);
System.out.println("获得的单条数据 "+ele);//从0开始计数
list5.clear();
System.out.println("清空之后 "+list5);
}
public static void main(String[] args){
test2 t = new test2();
boolean flag = false;
do{
System.out.println("请选择执行第几个程序,如果想要终止,请输入N");
Scanner scan = new Scanner(System.in);
String ss = scan.next();
if(ss.equals("N")){
flag = false;
System.out.println("END!");
break;
}
switch(ss){
case "1":
t.run();
break;
case "2":
t.run2();
break;
case "3":
t.run3();
break;
case "4":
t.run4();
break;
}
}while(flag = true);
}
}
因为ArrayList比较基础,所以这边我没有将对象添加到里面去,而是做了一些基本的功能,以后其他的集合都可以用来参照。
2、LinkedList(链式存储可重复)
这个程序没有用到实体类里的任何方法
以下实现的功能是按姓名和年龄进行排序
package LinkedList20151204;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
public class linkedlist extends Student{
linkedlist(String name, int age) {
super(name, age);
// TODO 自动生成的构造函数存根
}
public static void main(String[] args) {
Student a = new Student("a", 21);
Student b = new Student("e", 22);
Student c = new Student("c", 11);
Student d = new Student("d", 19);
LinkedList<Student> studentList = new LinkedList<Student>();
studentList.add(a);
studentList.add(b);
studentList.add(c);
studentList.add(d);
System.out.println("-------按年纪排序--------");
Collections.sort(studentList, new SortByAge());
for (Student student : studentList) {
System.out.println(student.getName() + " / " + student.getAge());
}
System.out.println("-------按姓名排序--------");
Collections.sort(studentList, new SortByName());
for (Student student : studentList) {
System.out.println(student.getName() + " / " + student.getAge());
}
}
}
class SortByAge implements Comparator<Student> {
public int compare(Student o1, Student o2) {
return (o2.getAge() -o1.getAge() );
}
}
class SortByName implements Comparator<Student> {
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
}
/*
* Comparable & Comparator 都是用来实现集合中元素的比较、排序的
* 只是 Comparable 是在集合内部定义的方法实现的排序
* Comparator 是在集合外部实现的排序
* 所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。
*/
这边做了两个排序,像list接口里的集合好像都是要自己写排序的方法。实现Collections.Sort就可以了,还是比较方便的。
3、HashSet(无序,元素不可重复)
这个程序用到了实体类中的hashcode和equals
以下实现的功能是通过实现重写hashcode和equals来进行排序
package hashset20151216;
import java.util.HashSet;
import java.util.Iterator;
public class hashset extends Student{
hashset(String name, Integer age) {
super(name, age);
// TODO 自动生成的构造函数存根
}
/*
* 在实体类Student里重写了equals和hashcode可以实现去除重复元素的功能。
*
* 结论:如将自定义类用hashSet来添加对象,一定要覆盖hashcode()和equals()
* 覆盖的原则是保证当两个对象hashcode返回相同的整数,而且equals()返回值为True。
*/
public static void main(String[] args) {
Student a = new Student("e",23);
Student b = new Student("c",21);
Student c = new Student("d",22);
Student d = new Student("c",21);
HashSet<Student> studentList = new HashSet<Student>();
studentList.add(a);
studentList.add(b);
studentList.add(c);
studentList.add(d);
Iterator<Student> iterators = studentList.iterator();
while(iterators.hasNext()){
Student result = iterators.next();
System.out.println(result.getName()+" "+result.getAge());
}
}
}
虽然现在大部分的JDK都已经要求覆盖了hashcode,但如果使用自定义类进行添加的话,偷懒而没有设定equals(),就会造成返回的hashcode虽然结果相同,但在程序执行时会多次调用equals,从而影响程序执行的效率。
我们要保证相同对象返回的hashcode一定相同,但也要保证不同对象的hashcode尽可能不同。
4、TreeSet(无序,元素不可重复)
这个程序用到了实体类中的compareTo()方法
以下程序实现的是按年龄进行排序
package TreeSet20160107;
import java.util.Iterator;
import java.util.TreeSet;
public class treeset extends Student{
treeset(String name, Integer age) {
super(name, age);
// TODO 自动生成的构造函数存根
}
public static void main(String[] args) {
Student a = new Student("a",23);
Student b = new Student("b",21);
Student c = new Student("c",21);
Student d = new Student("d",24);
TreeSet<Student> studentlist = new TreeSet<Student>();
studentlist.add(a);
studentlist.add(b);
studentlist.add(c);
studentlist.add(d);
Iterator<Student> iterators = studentlist.iterator();
while(iterators.hasNext())
{
Student result = iterators.next();
System.out.println(result.getName()+" "+result.getAge());
}
<pre name="code" class="java">package hashmap20160107;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
public class hashmap extends Student{
hashmap(String name, Integer age) {
super(name, age);
// TODO Auto-generated constructor stub
}
public static void main(String[] args){
Student a = new Student("a",23);
Student b = new Student("b",21);
Student c = new Student("c",22);
Student d = new Student("d",21);
Map<String,Student> studentlist=new HashMap<String,Student>();
studentlist.put("1",a);
studentlist.put("2",b);
studentlist.put("3",c);
studentlist.put("4",d);
/**
* 方法一遍历map,推荐使用该方法遍历map集合,尤其是容量大时
*
* entry用来迭代map
* keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
* Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry。它表示Map中的一个实体(一个key-value对)。
* 接口中有getKey(),getValue方法。
*/
for(Map.Entry<String, Student> entry : studentlist.entrySet()){
System.out.println(entry.getKey()+"="+entry.getValue().getName()+" "+entry.getValue().getAge());
}
System.out.println("**********************");
/**
* 方法二遍历map
*/
Set<Entry<String, Student>> entrySet = studentlist.entrySet();
for(Iterator<Map.Entry<String, Student>> iterator = entrySet.iterator();iterator.hasNext();){
Map.Entry<String, Student> entry = iterator.next();
System.out.println(entry.getKey()+"="+entry.getValue().getName()+" "+entry.getValue().getAge());
}
}
}
}}/* * 当要比较的元素相同时,treeset就会去除相同的元素,从而删除整个对象,但其实对象并不相同啊。这里很奇怪。 */ 这边要给TreeSet实现排序还是比较简单的,但是为什么会根据一个相同的属性去除明明是两个不同的对象,我就不是很明白了。
在CSDN上查找了一下,发现@
qybao 的解释
但 TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。
原帖:
http://bbs.csdn.net/topics/380106821 【TreeSet判断元素重复的问题】
5、HashMap(无序,不可重复)
这个程序没有用到实体类中的任何方法,实现的功能为按age排序
package hashmap20160107;
import java.util.*;
import java.util.Map.Entry;
public class hashmap extends Student{
hashmap(String name, Integer age) {
super(name, age);
// TODO Auto-generated constructor stub
}
public static void main(String[] args){
Student a = new Student("a",23);
Student b = new Student("b",21);
Student c = new Student("c",22);
Student d = new Student("d",21);
Map<String,Student> studentlist=new HashMap<String,Student>();
studentlist.put("1",a);
studentlist.put("2",b);
studentlist.put("3",c);
studentlist.put("4",d);
List<Map.Entry<String, Student>> studentlist2 = new ArrayList<Map.Entry<String, Student>>(studentlist.entrySet());
Collections.sort(studentlist2, new Comparator<Map.Entry<String, Student>>()
{
public int compare(Map.Entry<String, Student> o1, Map.Entry<String, Student> o2)
{
if(o2.getValue().getAge().compareTo(o1.getValue().getAge())>0){
return 1;
}
else{
return -1;
}
}
});
//参考http://blog.csdn.net/fly_fish456/article/details/8204298
Iterator<Map.Entry<String, Student>> it = studentlist2.iterator();
while(it.hasNext())
{
Map.Entry<String,Student> entry =(Map.Entry) it.next();
String name = entry.getValue().getName();
int age = entry.getValue().getAge();
System.out.println(name+" "+age);
}
/**
* 方法一遍历map,推荐使用该方法遍历map集合,尤其是容量大时
*
* entry用来迭代map
* keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
* Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry。它表示Map中的一个实体(一个key-value对)。
* 接口中有getKey(),getValue方法。
*/
/*
for(Map.Entry<String, Student> entry : studentlist.entrySet()){
System.out.println(entry.getKey()+"="+entry.getValue().getName()+" "+entry.getValue().getAge());
}
System.out.println("**********************");
//方法二遍历map
Set<Entry<String, Student>> entrySet = studentlist.entrySet();
for(Iterator<Map.Entry<String, Student>> iterator = entrySet.iterator();iterator.hasNext();){
Map.Entry<String, Student> entry = iterator.next();
System.out.println(entry.getKey()+"="+entry.getValue().getName()+" "+entry.getValue().getAge());
}
*/
}
}
这里做了一个按年龄排序的功能。HashMap里按照Key值进行排序很好做,但是按照Value值排序真的很难做,我在网上查找了大量的资料才写出了上面这个不是很完美的程序。
而且其实也算是稀里糊涂的改来改去发现就可以了。。。只能在以后遇到更实际的问题时再做研究了。
然后注释的部分是在没有实现排序的情况下做的两种遍历的方法,map的遍历也是很有趣,有很多种的遍历。
注:在实现查询的时候,如果是使用的是SET,那么必须全部遍历,所以效率比较低。而map因为采取的是KEY-VALUE对应的形式,所以查询的效率比较高。
注意:HashMap与HashCode有关,用Sort对象排序。
如果在HashMap中有key值重复,那么后面一条记录的value覆盖前面一条记录。
6、TreeMap(有序,不可重复)
这个程序没有用到实体类的任何方法,实现的功能为排序
package treemap20160111;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class treemap extends Student{
treemap(String name, Integer age) {
super(name, age);
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
Student a = new Student("a",23);
Student b = new Student("b",21);
Student c = new Student("c",22);
Student d = new Student("d",21);
TreeMap<String, Student> studentlist = new TreeMap<String,Student>(new Comparator<String>(){
public int compare(String o1, String o2) {
//指定排序器按照降序排列
return o2.compareTo(o1);
}
});
/*
* TreeMap默认按照key值进行升序排序
* 如果指定排序器则可以实现按key值降序排序
*/
studentlist.put("1",a);
studentlist.put("2",b);
studentlist.put("5",c);
studentlist.put("4",d);
//TreeMap遍历的两种方法 http://remind.iteye.com/blog/228073
Iterator it = studentlist.entrySet().iterator();
while(it.hasNext())
{
Map.Entry<String,Student> entry =(Map.Entry) it.next();
String name = entry.getValue().getName();
int age = entry.getValue().getAge();
System.out.println(name+" "+age);
}
}
}
因为TreeMap本来就自带按KEY值降序排序的功能,所以还是比较好的,当然也可以就指定比较器,将之按降序排序。
7、总结
各个集合都有自己的优缺点吧,自然是要根据具体的情况来选择集合,考验功力的时候到了。
不过我们有这么多的前辈已经给我总结了大概的使用效率。
集合中常用的是:ArrayList,HashSet,HashMap。其中ArrayList和HashMap使用最为广泛。
常用自然是因为效率高。
ArrayList VS LinkedList ArrayList是以数组的形式保存的,所以插入删除都很麻烦,但是查询效率高。LinkedList是以链式存储的,插入删除简单,查询麻烦。
HashSet VS TreeSet HashSet非常的消耗空间,TreeSet因为有排序功能,因此资源消耗非常的高,我们应该尽量少使用,而且最好不要重复使用。除非必须排序,不然使用HashSet。
HashMap VS TreeMap 一般使用HashMap,排序的时候使用TreeMap。
8、添加知识点:
集合对象存放的是一系列对象的引用。例:
Student S
Al.add(s);
s.setName(“lucy”);
Student s2=(Student)(al.get(o1));
可知s2也是s。