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

(一)链表的特点:
(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(obj==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接口。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值