黑马程序员__集合问题整理

来源:互联网 发布:中文域名有价值吗 编辑:程序博客网 时间:2024/06/05 08:22

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

 

 

1.集合对象的由来和特点。

       由来:数据多了就要封装成对象,即用对象存,而对象多了就要用集合存储,不能全部用StringBuffer来存,因为它最终会将其转为字符串。

       特点:是一个可以存储多种类型对象的容器,而且长度可变。

 

2.集合和数组的异同点?

异:1.集合的长度可变,而数组的长度固定;

       2.数组可以存储基本数据类型和引用数据类型,而集合只能存储引用数据类型;

同:都是一个容器。

 

3.集合体系由来?

       因为每个集合中的数据结构不同,所以集合有很多种,但都具有共性功能,就不断向上抽取,形成了集合框架,顶层为Iterator接口。

 

4. 了解一下顶层集合中的共性方法有哪些?

       (因为顶层集合中的方法是所有集合不断向上抽取出来的,所有集合都具备的共性方法,了解顶层方法就知道整个集合框架的基本功能。)

添加元素

add(Object)  添加一个元素
addAll(Collection)  添加一个Collection集合中的所有元素
删除元素 

clear() 删除该集合中的所有元素
remove(Object)  删除该集合中指定的元素

removeAll(Collection) 删除指定集合中的所有元素

判断元素

isEmpty()   返回boolean,判断该集合是否为空
contains(Object) 返回boolean,判断该集合中是否包含某个元素
containsAll(Collection)  返回boolean,判断该集合中是否包含直接集合中的所有元素

取出元素 

iterator() 返回在该集合的元素上进行迭代的迭代器(Iterator),用于遍历该集合所有元素      

其他功能 

size() 返回int值,获取该集合元素个数
toArray()  返回包含此 collection 中所有元素的数组

 

5. 迭代器是什么?

迭代器必须得依赖于容器,所以将它定义在容器中作为一个内部

类,被私有,对外提供访问规则Iterator接口,让容器中的内部类去实现它。

 

6.集合中常见的两个子体系及特点?

       List:存入的顺序和取出的顺序一致,元素有索引,能存在重复的元素;

       Set:不能存在重复的元素,确保元素的唯一性。

 

7.List体系中的常见的特性方法?

       add(index,obj)

       addAll(index,collection)

       get(index)

       indexOf(obj)

       lastIndexOf(obj)

       remove(index)

       set(index,obj)

       subList(begin,end)

 

8. List中的常见的子类对象,以及它们的特点?

       Vector:底层数据结构是一个长度可变的数组,同步的;

       ArrayList:底层数据结构是一个长度可变的数组,不同步的,开辟连续空间,对查询元素速度很快,效率高;

       LinkedList:底层数据结构是链表,开辟不连续的空间,对元素的增删改查操作很快,不同步的。

 

9.HashSet结构是什么?该结构有什么特点?

       哈希表结构,添加元素时,按照哈希算法hashCode()算出该元素的地址,若该地址空则存储,若该地址有元素,则通过equals方法判断是否为同一对象,不是同一对象则顺延一个位置进行存储,是则不存入。

 

10.HashSet是如何保证元素唯一性的。

       判断元素的hashCode是否相同,如果相同,还会继续判断equals方法是否为真。

       通过覆写hashCode方法定义自己的算法算元素哈希码,若元素哈希码相同则进一步根据自己的需求覆写equals判断是否同一对象,同一对象

则不存入,保证唯一。

       根据对象自身的特点判断哈希值是否相同。

 

11.TreeSet结构及其特点?

       二叉树结构,能够对元素排序,在添加元素的时候,将第一个元素作为根节点,每进来一个元素就与已有元素进行比较compareTo,然后根据二叉树结

    构找到它的存储位置,如果两个元素通过compareTo比较后返回0,则视为相等,新元素就不能进入集合。元素多的情况下,进行折半比较。

 

12.TreeSet如何保证元素唯一性。

       保证唯一:通过compareTo方法的返回值,若为0则相同对象,不能进入集合。

      

13.TreeSet两种排序方式,有什么区别?

       自然顺序:让元素本身具备比较性,对象实现Comparable接口,覆写compareTo方法,让元素具备了自然排序;

       比较器:让容器具备比较性,而且是添加元素之前,所以在容器创建时,定义一个Comparator子类对象实现该接口,覆写compare方法,并将该子类对象作为参数传递给容器的构造函数。

 

       区别:自然顺序排序这种方式有弊端,如果元素具备的自然排序不是所需的,而且元素可能本身就不具备比较性,但较为方便;

而比较器这种方式较为灵活,可以根据需求覆写compare方法来比较对象的大小进行排序。

      

14.查阅集合的技巧?

       通过名称获得数据结构,前缀名是数据结构的名称,后缀名是所属体系的名称,凡是后缀名是体系名称的集合通常都是不同步的;

       ArrayList:可变长度的数组,想到索引,查询速度快,不同步的;

       LinkedList:链表结构,增删速度快,不同步的,而且要记得addFirst,getFirst,removeFirst,addLast,getLast,removeLast方法;

       HashSet:哈希表结构,查询速度快,覆写hashCodeequals方法;

       TreeSet:二叉树结构,按照自然顺序排序,较HashSet效率低,实现Comparable接口覆写compareTo方法,或者定义一个Comparator子类实现接口,覆写compare方法。

 

15.泛型类,泛型方法,泛型接口什么时候用?并举例!

    泛型类:(只要使用的类或者接口上定义了<>)当类中操作的数据类型不确定时,可以在类上定义泛型,提供接收类型的参数即可;class Demo<>

    泛型方法:当类中的方法操作的数据类型不确定时,可以将泛型定义在方法上;如Person类中一个方法操作student类,另一个方法操作worker类;

泛型接口:在实现泛型接口时,实现类本身也不知道操作哪个类型,也在类上定义泛型;Comparator<T>;

 

16.泛型的通配符,以及泛型的限定的表现形式,和用法,以及什么时候用?

       ? extends E: 存储元素对象的时候用,你定义的是E类型,我们可以存储E类型或者E的子类型的对象。

       ? super E:从容器中取出元素时使用,容器中有E类型对象,取出时可使用E类型接收,或者E的父类型接收。比如比较器。

 

17.Map集合的使用场景。要求:查表法回顾一下,并用map集合完成一次查表法。

在分析问题时,如果其中出现了映射关系,就要首先想到map集合进行存储。map其实就是一个对应关系表,

查表法就用在map上,如果映射关系的数量是固定的,而且其中对应关系的一方是有编号(索引)的,就可以用数组进行存储。

用查表法解决月份的中英文翻译:

用数组来解决:

private static final String month[]=

{"" ,"January" ,"February" ,"March","April","May","June","July","August","September","October","November","December"};

Map表来解决:

建立Map表,输入一月到十二月的对应关系,该表是基本表,变化较少,可以单独封装,返回引用

 

18.Map集合和Collection集合的区别?    1

       Map中一次存储是键值对。

       Collection中一次存储是单个元素。

       2

       Map的存储使用的put方法。

       Collection存储使用的是add方法。

       3

       Map的取出,是讲Map转成Set,在使用迭代器取出。

       Collection取出,使用就是迭代器。

       4

       如果对象很多,必须使用容器存储。

       如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,

       如果没有映射关系,可以使用Collection存储。

 

19.Map集合中,取出所有元素原理,以及keySet,entrySet方法的使用,必须会?

       第一种方法,方法Set<K> keySet()得到键的Set集,遍历该Set集,对每一个键,调用MapV get(Object key)方法就可以得到该键对应的值

第二种方法,方法Set<Map.Entry<K,V>> entrySet()得到映射关系的Set集,遍历该Set集,对每一个映射元素,调用Map.Entry<K,V>类的方法K getKey()得到其键,调用V getValue()得到其值

第三种方法,方法Collection<V> values()得到值的Set集,遍历该Set集可以取出所有的值。

 

20.Map集合的特点以及常见子类的特点?
       Map:一次存储一对键值对元素,键值间存在映射关系;键一定不能重复,保证键的唯一性;Map集合中存储的就是键值间的映射关系。

       HashMap:哈希表数据结构,不同步的,允许使用null的键和值;

       Hashtable:哈希表数据结构,同步的,不允许使用null的键和值,效率较HashMap低;

       TreeMap:二叉树数据结构,不同步的,可以对Map中的键进行指定的方式排序,默认使用自然排序。

 

21.泛型的细节?

1、不可以用一个本地类型(如int,float)来替换泛型.比如List<Integer>不能用List<int>型式

2、运行时类型检查,不同类型的泛型类是等价的(Pair<String>Pair<Employee>是属于同一个类型 Pair),这一点要特别注意:即如果a instanceof Pair<String>==true的话,并不代表a.getFirst()的返回值是一个String类型

3、泛型类不可以继承Exception类,即泛型类不可以作为异常被抛出

4、不可以定义泛型数组

5、不可以用泛型构造对象,即T first = new T();是错误的

6、在static方法中不可以使用泛型,泛型变量也不可以用static关键字来修饰

7、不要在泛型类中定义equals(T x)这类方法,因为Object类中也有equals方法,当泛型类被擦除后,这两个方法会冲突

8、根据同一个泛型类衍生出来的多个类之间没有任何关系,不可以互相赋值,即

Pair<Number> p1; Pair<Integer> p2;   p1=p2;这种赋值是错误的。

9、若某个泛型类还有同名的非泛型类,不要混合使用,坚持使用泛型类  

       另外:泛型是用在编译时期的技术;

              提高了类型的安全性;

              避免了类型强制转换的麻烦;

              将问题转移到编译时期;

 

22.MapCollection的区别?

       1.Map一次存储一对值,而且是键值对,键和值之间存在着映射关系;而Collection中一次存储单个元素、对象;

       2.Map中的键一定要保证唯一性,若键重复,值被覆盖;而Collection中的子接口List集合中可以有重复元素;

       3.Map中存储的是键值对的映射关系,似一张对应关系表;而Collection存储的是任意类型的引用数据类型。

 

23.Map的练习(字母次数),明确查表的应用,注重思想?

       思路:1.将字符串变为字符数组;

             2.定义一个Map集合来存储字母和次数之间的关系;

             3.遍历字符数组,将字符数组中的元素作为键来查Map集合中是否存在相对应的值;

             4.定义一个变量来存储出现次数,初始化为0

             5.若存在,则返回相应的值,然后自增后,将键值对存入Map集合中;

             6.若不存在,则返回1;再存入集合中;

             7.得到了Map集合中的所有键值关系,就要将它们通过指定格式打印出来;

             8.所以将它们转成字符串,定义一个容器StringBuilder

 

24.Collecitons中常见方法举例?

       sort():对集合中的元素进行自然排序;

       max():对集合中的元素求最大值;

       binarySearch():对集合中的元素进行二分查找,若找到返回元素在聚合中的位置,若不存在则返回(-插入点-1);

       reverse():将集合中的元素进行反转;

       reverseOrder():强行逆转实现了comparable接口的对象collection中的元素;返回一个比较器;

 

25.CollectionCollections的区别?

       1.Collections是集合框架中的工具类,定义了一些用于操作集合的工具方法,这些方法都是静态的,没有对外提供构造函数,其中包括sortlist集合中的元素进行自然排序,还有max方法对集合中的元素求最大值,binarySearch方法进行元素的二分法查找,如果找到了则返回元素在集合中的位置,如果没有找到则返回(-插入点-1)reverse对集合中元素反转,reverseOrder强行将集合中的元素逆转,返回一个比较器;而且里面还包括将非同步的集合转为同步集合的方法,便于多线程集合使用;

2.Collection 是一个接口,是集合框架中的顶层单列集合,它的子接口有ListSet,

       List 集合是有序的(存入顺序和取出顺序一致),该集合中的元素都有索引,能够存在重复的元素;

       Set集合中不能保证元素的有序性,不允许存在重复元素,确保了元素的唯一性;

       List 又有常见的子实现类Vector,LinkedList,ArrayList;

       Vector 底层数据结构是一个长度可变的数组,同步的,它有一个特有方法elements()等同于迭代器Iterator,返回元素的取出方式,这个类是最早的集合;

 

26.Arrays常见方法?

       List<T> asList(T[])——将数组转成List集合,基于固定长度的数组

       二分查找

       排序

       变成字符串

 

27.数组和集合转换,数组转集合为什么?集合转数组为什么?要注意什么?

       toArray(T[] a)——集合转成数组,为了限定集合的方法对元素的操作,尤其是增删

       List<T> asList(T[])——将数组转成List集合,基于固定长度的数组

       就可以使用集合的方法操作数组中的元素,

       但是,增删这种改变数组长度的方法不可使用

       最终操作的还是这个数组,不能把原数组长度改变了

 

28.Runtime api查阅时,你看到了什么,想到了什么?

类中没有构造方法,不能创建对象。

但是有非静态方法。说明该类中应该定义好了对象,并可以通过一个static方法获取这个对象。用这个对象来调用非静态方法。这个方法就是 static Runtime getRuntime();

想到了单例设计模式

 

29.foreach可以遍历map吗?

高级for循环在使用时,必须要明确被遍历的目标。这个目标,可以是Collection集合或者数组,如果遍历Collection集合,在遍历过程中还需要对元素进行操作,比如删除,需要使用迭代器。不可以。但是可以将map转成set后再使用foreach语句

 

30.System类中获取本地系统信息的方法。

Properties prop = System.getProperties();

//获取系统的属性信息,并将这些信息存储到Properties集合中。

line.separator//行分隔符

static Properties getProperties()——取出全部

static String getPropertykey)——取出对应

 

31. Math中的常见方法使用?

static double ceil(double a) ; //返回大于指定数值的最小整数

static double floor(double a) ; //返回小于指定数值的最大整数

static long round(double a) ; //四舍五入成整数

static double pow(double a, double b) ; //ab次幂

static double random(); //返回0~1的伪随机数

Random类来取随机数,伪随机数——算法算出来的!

 

32.数组和集合的互相转化

*List asList([]):将数组转成List集合。

//deepEquals(o1,o2):先判断对象是否相等,再判断对象中的内容是否相等;

//toString(arr):将数组变成字符串;替代了数组的遍历,方便于数组的打印;

asList(arr):相同于CollectiontoArray方法,将数组转成集合;返回List

              *List<int []>  list=Arrays.asList(nums);//数组只能转成List集合

               * 数组转成集合有什么好处?

               * 就可以使用集合的方法操作数组中的元素。

               * 但是,有些方法不能用,增删这种改变数组长度的方法不可以使用。

               * 一旦使用,会发生UnsupportedOperationException

* 集合转成数组toArray()

               * 为什么要集合转成数组呢?

               * 其实为了限定集合的方法对元素的操作,尤其是增删。

 

33.Properties:

里面存入的键值都是字符串,能延长键值对的生命周期;

       System 类不能被实例化,对外部提供属性和环境变量的访问;提供了操作便准输入输出设备的属性。

       in:键盘

       out:显示器

       exit():退出虚拟机;

       gc():启用垃圾回收;

       currentTimeMillis():返回当前时间的毫秒值;

       getProperties():确定当前的系统属性;

       stringPropertiesName():Map集合转成Set,取出元素的一种方式;

       getProperty(key):获取指定键的值;

       getProperty(line.sepaeator):通过这个键获取系统平台下的的换行符;

 

练习. "fdgavcbsacdfs"获取该字符串中,每一个字母出现的次数。要求打印结果是:a(2)b(1)...;

 

import java.util.Iterator;

import java.util.Map;

import java.util.TreeMap;

 

public class MapTest {

 

         public static void main(String[] args) {

 

                   /*

                    * 思路: 1,既然要获取的是字母出现的次数,说明字母和次数之间存在对应关系。

                    * 2,而且字母有很多,意味着对应关系有很多,数据多了一定要进行存储。 3,对应关系个数确定不?不定义。可以考虑使用map集合。

                    * 4,将字符串中每一个字母作为键去查map这张表。

                    * 如果该键有对应的次数,就将该次数取出并进行自增后,将该键和自增后的值重新存储,键相同,值覆盖。

                    * 如果该键没有对应的次数,就将该键和1存储到map表中。 5,当所有的字母被遍历完,map中存储就是每一个字母和其对应的次数。

                    */

 

                   String str = "fdgavcbsacdfs";

                   String charCount_str = getCharCount(str);

                   System.out.println(charCount_str);

 

         }

 

         public static String getCharCount(String str) {

 

                   // 1,将字符串变成字符数组。

                   char[] chs = str.toCharArray();

 

                   // 2,创建一个map集合,存储字母和次数的对应关系表。使用TreeMap对键进行排序。

                   Map<Character, Integer> map = new TreeMap<Character, Integer>();

 

                   // 3,对字符数组进行遍历。

                   for (int i = 0; i < chs.length; i++) {

 

                            // 如果仅要字母。不需要其他字符。

                            if (!(chs[i] >= 'a' && chs[i] <= 'z' || chs[i] >= 'A'

                                               && chs[i] <= 'Z')) {

                                     continue;

                            }

 

                            // 通过字母作为键去查map表。获取对应的值。

                            Integer value = map.get(chs[i]);

                            // 为了方便记录次数,定义一个计数器。 count.

                            int count = 0;

 

                            // 如果值不为null,就对将该值进行记录。

                            if (value != null) {

                                     count = value;

                            }

                            // 对记录的次数进行自增如果没有value值,count自增为1.

                            count++;

                            map.put(chs[i], count);//将当前的键和自增后的值进行存储。

                   }

                   return mapToString(map);

         }

 

         private static String mapToString(Map<Character, Integer> map) {

 

                   // map中的键值对变成指定格式的字符串。

                   // 数据有很多,最终变成字符串。哎呀!让我想到了一个容器。StringBuilder

 

                   StringBuilder sb = new StringBuilder();

 

                   // 迭代集合。

                   Iterator<Map.Entry<Character, Integer>> it = map.entrySet().iterator();

                   while (it.hasNext()) {

 

                            Map.Entry<Character, Integer> me = it.next();

 

                            Character key = me.getKey();

                            Integer value = me.getValue();

                            sb.append(key + "(" + value + ")");

                   }

 

                   return sb.toString();

         }

 

}

 

 

 

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

 

原创粉丝点击