您的位置:首页 > 其它

List接口与Set接口及其子类的详细用法。Collection接口简介。ArraList,LinkedList,Vector

2018-03-29 15:54 495 查看
(一)链表的特点:
(1)这种节点关系的处理操作,核心需要一个Node类(保存数据,设置引用)
(2)在进行链表数据的查找,删除的时候需要equals()方法的支持。
在实际的开发中对于这些数据的使用都有一些共性的特点:存储进去而后取。
     
     
   (二)Java类集框架
   1 Collection集合接口  
 (1)具体内容
  在java的类集里面(java.util包)提供两个最为核心的操作接口:Collection,Map接口,
其中Collection接口的操作与之前编写链表操作的形式类似,每进行一次数据操作的时候只能对单个对象进行处理。
所以Collection是单个集合保存的最大父接口。 Collection接口定义如下:
public interface Collection<E>extends Iterable<E>
从jdk1.5开始发现Collection接口上追加有泛型应用,这样的直接好处就是可以避免了ClassCastException,里面的所有的
数据的保存类型应该是相同的。

Iterabl接口中有方法  +iterable():Iterable<T>
Collection接口中有方法   public boolean add(E e)//向集合中添加数据
                        public boolean addAll(Collection<?extends E>c)//向集合中添加一组数据
                        public void clear() //清空集合数据
                        public boolean contains(Object o) //查找数据是否存在,需要使用equals()
                        public boolean remove(Object o)//删除数据,需要equals方法
                        public int size()//取得集合长度
                        public Object[] toArray()//将集合变为对象数组返回
                        public Iterator<E>iterator()//取得Iterator接口对象,用于输出
                                              重点看第一个和最后一个方法
Collection接口中有List接口(允许重复)和Set接口(不允许重复)这两个子接口。还有就是Set接口并没有对Collection接口进行扩充。List接口进行了扩充。
(2)List接口
在实际开发项目中,优先考虑List集合接口 。其中的一些重要方法:
public E get(int index)//根据索引取得保存的数据                  
public E set(int index,E element)//修改数据
List子接口和Collection接口的最大特点在于其有一个get()方法,可以根据索引取得内容。而List本身还属于一个接口,如果想要取得接口的实例化对象,就必须有子类。
List接口下有三个常用子类:ArrayList,Vector,LinkedList.

(3)ArrayList类
ArrayList是一个针对于List接口的数组操作实现。
示例:
public class Test {

public static void main(String[] args) throws Exception {
List<String> all=new ArrayList<>();//此集合中只允许保存String数据类型
System.out.println(all.size()+","+all.isEmpty());//看集合目前的大小以及是否为空
all.add("hellow");
all.add("hellow");//重复输入
all.add("world");
all.remove("hellow");// 删除数据,需要equals方法
System.out.println(all.size()+","+all.isEmpty());//看集合目前的大小以及是否为空
System.out.println(all.contains("ABC"));//查找数据是否存在,需要使用equals()
System.out.println(all.contains("world"));//查找数据是否存在,需要使用equals()
System.out.println(all);

}

}

输出结果0,true
2,false
false
true
[hellow, world]
  所以也证明了List接口允许重复。

(4)观察List的get操作
public class Test {

public static void main(String[] args) throws Exception {
List<String> all=new ArrayList<>();//此集合中只允许保存String数据类型
all.add("hellow");
all.add("hellow");//重复输入
all.add("world");
for(int x=0;x<all.size();x++)
{
System.out.println(all.get(x));
}

}

}
结果如下:
hellow
hellow
world

注意:get方法是List子接口的,如果现在使用的不是List而是Collection,那么对于此时的数据取出你只能将集合变为对象来取出。
示例:用Collection接口进行数据的输出(尽量不用这种操作)
public class Test {

public static void main(String[] args) throws Exception {
Collection<String> all=new ArrayList<>();//此集合中只允许保存String数据类型,注意list是collection的子接口,ArrayList是List子类
all.add("hellow");
all.add("hellow");//重复输入
all.add("world");
//操作一object的形式返回,那么就有可能向下转型,可能造成安全隐患
Object [] result=all.toArray();//变为object对象数组
System.out.println(Arrays.toString(result));
}
}

(5)List与简单java类。
下面的这个例子在实际开发中出现的几率是很低的
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

class Person
{
     private String name;
     private Integer age;//Integer和int最大的区别在于前者能为空
     public Person(String name,Integer age)
     {
       this.name=name;
            this.age=age;
     }
     
     public boolean equals(Object obj)
     {
    if(this==obj)
    {
    return true;
    }
    if(ob
4000
j==null)
    {
     
    return false;
    }
    if(!(obj instanceof Person))
    {
    return false;
    }
    Person per=(Person)obj;//这个地方可以向下转型
    return this.name.equals(per.name)&&this.age.equals(per.age);
     }

     public String toString()
     {
    return "Person [name="+this.name+",age="+this.age+"]";
     
     }

}

public class Test {

public static void main(String[] args) throws Exception {
List<Person> all=new ArrayList<>();
all.add(new Person("张三",12));
all.add(new Person("李四",11));
all.add(new Person("王五",18));
//对于集合中的remove(),contains()方法必须类中有equals的支持。
/*
*   public boolean contains(Object o) //查找数据是否存在,需要使用equals()
             public boolean remove(Object o)//删除数据,需要equals方法
*/
all.remove(new Person("张三",12));
       System.out.println(all.contains(new Person("李四",11)));
for(int x=0;x<all.size();x++)
{
System.out.println(all.get(x));

}

}

}
结果如下:
true
Person [name=李四,age=11]
Person [name=王五,age=18]

(6)Vector类与ArrayList类的区别(在用法上,就是将ArrayList换成Vector即可)
                            处理形式                                          数据安全                     输出形式

Vector        同步处理,性能降低                                       线程安全                Iterator,ListIterator,foreach,

ArrayList   异步处理,性能更高                                           非线程安全              Iterator,ListIterator,foreach

  (7)Linkedlsit类与ArrayList区别(在实际开发中,Linkedlsit的用法就是将ArrayList进行替换即可)
  ① ArrayList中放的是数组,如果在实例化此类对象的时候,默认传入了数组的大小(List<Person> all=new ArrayList<>(2);),则里面保存的数组就会开辟一个定长的数组。
    但是如果后面再进行数据保存的时候发现数组的个数不够了,那么会进行数组的动态扩充。如果要使用ArrayList最好的做法就是设置初始化的大小。以分页的程序为例,
    每次只会取出指定行的内容。
 ② Linkedlsit是一个纯粹的链表实现。
总结:ArrayList封装的是一个数组,Linkedlsit封装的是一个链表实现。ArrayList的时间复杂度为1,因为能通过索引直接定位,而Linkedlsit时间复杂度为n。
    开发之中考虑的是ArrayList,如果考虑性能,一定要传入初始化大小。

(8)set接口
   ① Collection接口中有List接口(允许重复)和Set接口(不允许重复)这两个子接口。还有就是Set接口并没有对Collection接口进行扩充。List接口进行了扩充。
     在set接口中不能用get方法。在set接口中有两个常用的子类:HashSet(无序存储),TreeSet(有序存储)。
   ② 示例: 观察HashSet的使用

public class Test {

public static void main(String[] args) throws Exception {
Set<String> all=new HashSet<>();
all.add("hellow");
all.add("hellow");
all.add("world");
System.out.println(all);

}
}
结果是:[hellow, world]。可以看出set接口是不允许重复 的。

示例:TreeSet的使用

public class Test {

public static void main(String[] args) throws Exception {
Set<String> all=new TreeSet<>();
all.add("c");
all.add("c");//重复
all.add("a");
all.add("b");
all.add("d");
System.out.println(all);
}
}

结果是:[a, b, c, d]   可以看出TreeSet的结果是按照升序排列的。set接口是不允许重复的。

(9)TreeSet排序分析
示例:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
//.java中可以有多个类,但是只能有一个public公共类。
//
class Person 
{
private String name;
private Integer age;
public Person(String name,Integer age)
{
this.name=name;
this.age=age;
}
//一般这个方法使用来把其他类型的数据转为字符串类型的数据的。
public String toString()
{
return "Person name="+this.name+",age="+this.age+"\n";
}

}

public class Test {

public static void main(String[] args) throws Exception {
Set<Person> set=new TreeSet<>();
set.add(new Person("张三",23));
set.add(new Person("张三",23));//重复数据
set.add(new Person("李四",23));//年龄重复
set.add(new Person("王五",29));
System.out.println(set);

}
}
结果是:Exception in thread "main" java.lang.ClassCastException: 类集概述及相关集合接口.Person cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1188)
at java.util.TreeMap.put(TreeMap.java:531)
at java.util.TreeSet.add(TreeSet.java:255)
at 类集概述及相关集合接口.Test.main(Test.java:29)
可以通过TreeSet实现数据的排列处理操作,但是在这个例子中,若进行数据的排序,实际上是针对对象数组进行的排序,若要进行对象数组的排序,那么对象所在的类一定要
实现Comparable接口,重写compareTo()方法。因为只有通过此方法才能知道大小关系。
改正后:
import java.util.Set;
import java.util.TreeSet;
//.java中可以有多个类,但是只能有一个public公共类。
//
class Person implements Comparable<Person>
{
private String name;
private Integer age;
public Person(String name,Integer age)
{
this.name=name;
this.age=age;
}
//一般这个方法使用来把其他类型的数据转为字符串类型的数据的。
public String toString()
{
return "Person name="+this.name+",age="+this.age+"\n";
}
//这时候要对所有的属性进行比较
public int compareTo(Person o)
{
if(this.age>o.age)
{
return 1;
}else if(this.age<o.age)
{
return -1;
}else
{
return this.name.compareTo(o.name);
}
}
}

public class Test {

public static void main(String[] args) throws Exception {
Set<Person> set=new TreeSet<>();
set.add(new Person("张三",23));
set.add(new Person("张三",23));//重复数据
set.add(new Person("李四",23));//年龄重复
set.add(new Person("王五",29));
System.out.println(set);

}
}
结果:[Person name=张三,age=23
, Person name=李四,age=23
, Person name=王五,age=29
]
用TreeSet进行排序要对所有的属性进行比较,所以太麻烦了。set接口不允许重复。

(10)使用HashSet类时判断重复元素需要依靠Object类中的两个方法:
hash码:public int hashCode();
对象比较:public boolean equals(Object obj)
在java中进行对象比较的操作需要两步:第一步,通过一个对象的唯一编码找到一个对象的信息,当编码匹配之后再调用equals()方法进行内容的比较。
需要注意的是hashCode和equals方法都可以通过在source中找到generate hashCode()和equals()自动生成这两个方法。
如果想要标识出对象的唯一性,一定需要hashCode和equals这两个方法。

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
//.java中可以有多个类,但是只能有一个public公共类。
//
class Person implements Comparable<Person>
{
private String name;
private Integer age;
public Person(String name,Integer age)
{
this.name=name;
this.age=age;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}

  //一般这个方法使用来把其他类型的数据转为字符串类型的数据的。
public String toString()
{
return "Person name="+this.name+",age="+this.age+"\n";
}
//这时候要对所有的属性进行比较
public int compareTo(Person o)
{
if(this.age>o.age)
{
return 1;
}else if(this.age<o.age)
{
return -1;
}else
{
return this.name.compareTo(o.name);
}
}

}

public class Test {

public static void main(String[] args) throws Exception {
Set<Person> set=new HashSet<>();
set.add(new Person("张三",23));
set.add(new Person("张三",23));//重复数据
set.add(new Person("李四",23));//年龄重复
set.add(new Person("王五",29));
System.out.println(set);

}
}
结果:[Person name=张三,age=23
, Person name=李四,age=23
, Person name=王五,age=29
]

总结:在很多时候使用Set集合的核心目的不是让其进行排序,而是让其进行重复元素的过滤,那么使用treeset就没有意义。
但是重复元素需要依靠hashCode和equals两个方法消除,所以如果不是必须的时候,在使用set接口的时候尽量使用系统提供的类实现,例如String,Integer。

可以借鉴的原则:(1)保存自定义类对象时一定用List接口。(2)保存系统类的信息的时候一定用Set接口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息