黑马程序员_java集合整理

------- android培训、java培训、期待与您交流! ----------

 

1.由于数组的使用有长度的限制,因此就出现了类集(集合)集合中存放的是一组动态的数组对象。
2.collectiong是父接口,但是它并常用。它的子接口
BeanContext,BeanContextServices,BlockingDeque,BlockingQueue,Deque,List,NavigableSet,Queue,Set,SortedSet
3.List,它是collection的子接口。该接口
AbstractList,AbstractSequentialList,ArrayList,AttributeList,CopyOnWriteArrayList,LinkedList,RoleList,RoleUnresolvedList,Stack,Vector
4.arraylist是大小可变的数组的实现。list中的元素是可以重复的,甚至能包括null值。需要注意的是:arraylist的构造方法new arraylist()实际上时在底层生成了一个长度为10的数组。
代码演示arralist的用法:

 
  

package collectino; import java.util.ArrayList; import java.util.List; /** *这个例子主要是展示arraylist插入数据的用法,new arraylist()实际上是在底层生成了一个长度为10的数组 * @author Administrator * */ public class ArrayListTest { public static void main(String[] args) { List<String> str = new ArrayList<String>();//arraylist是接口list的实现类,该接口中允许重复元素的出现,这里使用到了多态 str.add("luochuang"); str.add(null); str.add(2,"luochuang");//表示从从某个特定的下标开始插入数据,add方法返回的boolean类型的数据,表示是否插入成功 //关于输出 System.out.println(str.toString());//这里实际上打印的是str引用指向的一组数组对象 for(String s:str) { System.out.println(s); } } }

5.arraylist类,反相输出


6.它有一个toarray方法返回的是一个object类型的数组。

7.关于arraylist和linkedlist的区别:
1).ArrayList是实现了基于动态数组的数据结构LinkedList基于链表的数据结构
2).对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针
3).对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据
其实最后两点总结起来的话:对于读取元素arraylist比较方便,而对于增加和删除元素linked比较方便。

关键词:set hashset treeset equals hashcode compable compareTo
1.set是collection中的另外一个接口,它和list所不同的的地方是:Set中存放的元素是不能重复的,并且它对collection接口进行了更大范围的扩充和元素限制。
2.set接口的子类:hashset,treeset它们中存放的元素也是不能重复的,并且hashset中的元素的存放顺序是散列的,而treeset中存放的元素的顺序是有序的,但是存放的类要先实现compable接口。

3.关于hashcode和equals()方法,在hashset的底层,如何区别他们是不是同一个元素呢?首先调用他们的hashcode的值,然后调用equals()判断他们是否是同一对象,为什么不直接使用hashcode或者是equals()方法来判断他们是否是同一元素呢?
1)使用equals()方法来判断元素是否是同一元素的时候,效率比较低,而hashcode方法相同他们的equals方法是可能不相同的,但是equals方法相同元素的hashcode的值则一定是相同的。

因为判断hashCode比判断equals高效的多,hashCode自有一套判断方法
所以如果equals方法判断是相等,但哈希值不一定相等,两个元素也就不一定相等;
因此这就带来了一个问题,hashCode判断和equals判断不同步,所以为了保持同步性,必须对这两个方法进行重写。

关键词:hashcode equals ==
1.
简单的说,==是判断两个变量或实例是不是指向同一个内存空间equals是判断两个变量或实例所指向的内存空间的值是不是相同 。
        String s="ddddd";
        String s2="ddddd";
        System.out.println(s.equals(s2));
        System.out.println(s==s2);
        System.out.println("=================================");
打印两个true.
java虚拟机有一个字符串池,这样声明的字符串都存放在这个池里,如果以后声明的字符串和先前声明的一样,那么就不建立新的字符串,而是两个字符串变量指向相同的引用了。
2.写过C++的代码人其实很容易理解char* str = "log something"; "log something"在编译时会把它放在常量区,str只是指到该常量的一个指针。其实,Java中的存也在类似的情况,只不过不是放在常量区,Java中叫常量池,目的是一致的。常量池中常量内容由ClassLoader加载到JVM中。

是这样的吗?下面我们来做个测试。

String str0=”something”;
String str1=”something”;
String str2=”some” + “thing”;
System.out.println( str0==str1 );
System.out.println( str0==str2 );

运行的结果是:

 true
 true


因为例子中的str0和str1中的”something”都是字符串常量,它们在编译期就被确定了,所以str0==str1为true而”some”和”thing”也都是字符串常 量当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量所以str2也同样在编译期就被解析为一个字符串常量,所以str2也是常量池中” something”的一个引用。

于是:str0==str1==str2 ,再套用C++的观点,str0,str1,str2都有指到同一块内存的内容。

我们要注意的是new String()产生对象不是在放在常量池中在编译期无法知道String的数据内容在运行期才能知道。下面我们再来做一个测试。

String str0=new String(”something”);
String str1=new String(”something”);
String str2=”some” + new String(“thing”);
System.out.println( str0==str1 );
System.out.println( str0==str2 );
System.out.println( str1==str2 );

运行的结果是:

 false
 false
 false


这是因为每个字符串为一个对象,比较是他们的引用地址,在堆分配的地址肯定是不一样的。于是:我们在表达一个字符串常量是,不用使用final String str0=new String(”something”);,这是多此一举,final也是多余的,那是因为String来就是一个final对象,一量生成,不可修改,即使String str0= str0.replace("o", "e")之类的写法,也会产量临时变量,str0再指向临时变量的引用。
3.equals.在java的Object类中“equals()”的实现如下:

1     public boolean equals(Object obj)  {
2           return (this == obj);
3     }


         我们可以看到在Object中“equals()”的实现指示简单的使用了“==”也就是之判断了,两个对象的引用相等。这也就是为什么我们在使用“equals()”时必须重写这个方法的原因了。

      在jdk的帮助文档中,对于“equals()”和“HashCode()”有这样的说法,如果两个对象使用equals()返回为true,则使用HashCode()必然返回的值必然相等,反之则不一定啊。


4.引用jdk中equal的特性:equals 方法在非空对象引用上实现相等关系:

  • 自反性:对于任何非空引用值xx.equals(x) 都应返回 true
  • 对称性:对于任何非空引用值xy,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回true
  • 传递性:对于任何非空引用值xyz,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回true
  • 一致性:对于任何非空引用值xy,多次调用 x.equals(y) 始终返回 true 或始终返回false,前提是对象上 equals 比较中所用的信息没有被修改。
  • 对于任何非空引用值 xx.equals(null) 都应返回false

5.equals 和hashcode判断向set中增加元素

1、当向集合Set中增加对象时,首先集合计算要增加对象的hashCode码,根据该值来得到一个位置用来存放当前对象,挡在该位置没有一个对象存在的话,那么集合Set认为该对象在集合中不存在,直接增加进去。如果在该位置有一个对象存在的话,接着将准备增加到集合中的对象与该位置上的对象进行equals方法比较,如果该equals方法返回false,那么集合认为集合中不存在该对象,在进行一次散列,将该对象放到散列后计算出的新地址里,如果equals方法返回true,那么集合认为集合中已经存在该对象了,不会再将该对象增加到集合中了。

2、重写equals方法的时候必须重写hashCode方法。如果一个类的两个对象,使用equals方法比较时,结果为true,那么该两个对象具有相同的hashCode。原因是equals方法为true,表明是同一个对象,它们的hashCode当然相同。

3、Ojbect类的hashCode方法返回的是Object对象的内存地址。可以通过Integer.toHexString(new Object().hashCode);来得到。


equals相同,则hashcode肯定相同,但是hashcode相同,equals则有可能相同。

 

Treeset 的自定义的两种排序方式

第一种:在元素中定义排序规则。元素自身具有比较性实现Comparable接口 覆盖compareTo方法

import java.util.Iterator;
import java.util.TreeSet;
/***
 *TreeSet是一个有序集合,TreeSet中元素将按照升序排列,缺省是按照
  自然顺序进行排列,意味着TreeSet中元素要实现Comparable接口。
  我们可以在构造TreeSet对象时,传递实现了Comparator接口的比较器对象。
  注意排序時:當主要的條件相同時,判斷次要條件。
 * @author Administrator
 *
 */
public class TreeSetTest {
 public static void main(String[] args) {
  TreeSet treeset = new TreeSet();//定义一个集合
  treeset.add(new person2(10, "liuyia"));
  treeset.add(new person2(10, "liuyib"));
  treeset.add(new person2(15, "liuyi34"));
  treeset.add(new person2(11, "liuyi4"));
  treeset.add(new person2(12, "liuyi4"));

  Iterator itera = treeset.iterator();
  while (itera.hasNext()) {
   System.out.println(itera.next());
  }

 }
}

class person2 implements Comparable {//实现Comparable 接口  private int age;

 private String name;

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public person2(int age, String name) {
  this.age = age;
  this.name = name;
  
  
 
 }


 public int compareTo(Object o) {
  if(!(o instanceof person2))
   throw new RuntimeException("對象不對哇!!");
   person2 p = (person2)o;
   if(this.age>p.age)
   {
    return -1;
   }
   if(this.age<p.age)
   {
    return 1;
   }
   
   if(this.age==p.age)
   { 
    return this.name.compareTo(p.name);//當主要的條件也就是age的值相同時時候此時判斷次要條件姓名
   }
   

  return -1;
  
 }
 //用於設置打印結果
 public String toString()
 {
  return age+" = "+"name"+name;
 }
}


第二种:在集合中定义排序  实现Comparator接口 覆盖compare方法。

TreeSet(Comparator comparator)
          构造一个新的空 TreeSet,它根据指定比较器进行排序。

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetTest {
 public static void main(String[] args) {
  TreeSet treeset = new TreeSet( new mycomp());//定义一个集合
  treeset.add(new person2(10, "liuyia"));
  treeset.add(new person2(10, "liuyib"));
  treeset.add(new person2(15, "liuyi34"));
  treeset.add(new person2(11, "liuyi4"));
  treeset.add(new person2(12, "liuyi4"));

  Iterator itera = treeset.iterator();
  while (itera.hasNext()) {
   System.out.println(itera.next());
  }

 }
}

class person2 {
 private int age;

 private String name;

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public person2(int age, String name) {
  this.age = age;
  this.name = name;
 }
 public String toString()
 {
  return age+" = "+"name"+name;
 }
}


class mycomp implements Comparator
{

 public int compare(Object o1, Object o2) {
  person2 p1 = (person2)o1;
  person2 p2 = (person2)o2;
  return -(p1.getAge()- p2.getAge());
 }
}

 

map的两种常用的遍历方式

1.map是以键值对的方式来存储元素的,在map中key是不能重复的,但是value可以重复,key中能保存空值,value也可以保存空值,当value中保存空值的时候表示的是该键上没有值,key的底层是set,value是集合collection。

hashmap的第一种遍历方式:keyset返回的是set的列表视图,通过遍历该列表视图,并调用map.gey(key)的方法来循环找到key对应的value,第一种方式的实现代码:

package Map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * map的第一种遍历方式
 * @author Administrator
 *
 */
public class maptest1 {
 public static void main(String[] args) {
  Map<String , String> map = new HashMap<String, String>();
  map.put("luochuang1", "luochuang1");
  map.put("luochuang2", "luochuang2");
  map.put("luochuang3", "luochuang3");
  map.put("luochuang4", "luochuang4");
  map.put("luochuang5", "luochuang5");  
  
  Set<String> set = map.keySet();//keyset返回的是key集合
  
  for(Iterator<String> iter = set.iterator();iter.hasNext();)
  {  
   String key = iter.next();
   String value = map.get(key);  
   System.out.println("key:="+key+"  "+"value:="+value);
  }
  
 }
}


2.遍历map的第二种方法,使用keyset()方法,map.entrySet()返回的是此映射中包含的映射关系的Set 视图。该 set 受映射支持,所以对映射的更改可在此 set 中反映出来,反之亦然。

package Map;
/**
 *  遍历map的第二种方法
 * 
 */
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class maptest2 {
 public static void main(String[] args) {
  Map<String , String> map = new HashMap<String, String>();
  map.put("luochuang1", "luochuang1");
  map.put("luochuang2", "luochuang2");
  map.put("luochuang3", "luochuang3");
  map.put("luochuang4", "luochuang4");
  map.put("luochuang5", "luochuang5");
  
  Iterator<Entry<String, String>> iter =map.entrySet().iterator();//map.entryset()返回的是映射集合
  
  while(iter.hasNext())
  {
   Map.Entry<String, String> entry =iter.next();//map接口中定义的接口
   String k = entry.getKey();
   String v =entry.getValue();
   System.out.println("key:="+k+"  " +"value:="+v);
  }
  
 }
}

 

------- android培训、 java培训、期待与您交流! ----------

你可能感兴趣的:(黑马程序员_java集合整理)