Java中的集合学习笔记

时间:2022-10-08 17:02:12

最近一直在看Java里的集合这块,初看觉得内容不多,细看之后发现东西真的很多。我的学习也还只是停留在初级阶段,这边我想做一个大概的整理。


这个是集合的大致分类,我只学习了一般用到的一些集合,其他更详细的暂时还没有学习。

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。