笔记:Java容器(下)

Queue

队列对并发编程很重要。将LinkedList向上转型为Queue,以下是常用方法

public class Command {
    private String s;
    public Command(String s) { this.s = s;}
    public String operation() { return s;}
    public static void main(String[] args) {
        Queue<Command> q = new LinkedList<>();
        UseCommand.use(FillCommand.fill(q, new Command("fuck1"), new Command("fuck2")));
    }
}
class FillCommand {
    public static Queue<Command> fill(Queue<Command> queue, Command... args) {
        for (Command c : args) queue.offer(c);
        return queue;
    }
}
class UseCommand {
    public static void use(Queue<Command> q) {
        while (!q.isEmpty()) { println(q.poll().operation());}
    }
}

PriorityQueue

优先级队列声明下一个弹出元素是最需要的元素。在优先级队列调用offer,这个对象在队列中会被排序。默认的排序将使用自然顺序。Integer、String和Character都内建了Comparator
,所以自然排序是值从小到大(空格有最大优先级)

public static void main(String[] args) {
        Queue<Double> q = new PriorityQueue<>();
        var rand = new Random();
        while (q.size() < 20) q.offer(rand.nextDouble()*100);
        while (!q.isEmpty()) println(q.poll());
    }

Collection和Iterator

Collection接口描述可以让我们创建更通用的代码。实现Collection意味着要提供Iterator方法
可以继承AbstractCollection代替实现Collection,虽然两者都要实现Iterator,但前者不用实现Collection中的其他方法。

public class CollectionSequence extends AbstractCollection<Pet> {
    private Pet[] pets = Pets.createArray(9);
    public int size() { return pets.length;}
    public Iterator<Pet> iterator() {  // 实现Iterator<>
        return new Iterator<>() {
            private int index = 0;
            @Override
            public boolean hasNext() { return index < pets.length; }
            @Override
            public Pet next() { return pets[index++];}
            public void remove() { throw new UnsupportedOperationException();}
        };
    }

    public static void main(String[] args) {
        var cs = new CollectionSequence();
        for (Pet p : cs) {
            print(p.id() + ": " + p + " ");
        }
        println();
        
        Iterator<Pet> it = cs.iterator();
        while (it.hasNext()) {
            Pet p = it.next();
            print(p.id() + ": " + p + " ");
        }
    }
}

Foreach与迭代器

foreach语句可以用于数组和其他任何Iterable,但数组不一定是一个Iterable。

public class ArrayNotIterable {
    static <T> void test(Iterable<T> ib) {
        for (T t : ib) println(t + " ");
    }

    public static void main(String[] args) {
        test(Arrays.asList(1, 2 ,3));  // ok
        String[] s = {"A", "B", "C"};
        // !test(s) s is not an iterable
        test(Arrays.asList(s));  // ok
    }
}

实现迭代器:

class RandomShapeGenerator implements Iterable<Shape>{  // randomly creates shapes...
    private Random rand = new Random();
    private int count;
    private ArrayList<Shape> s = new ArrayList<>(count);
    public RandomShapeGenerator(int count) { this.count = count;}
    public void next() {  // return a Shape reference randomly...
        switch(rand.nextInt(3)) {
            case 0: s.add(new Circle()); break;
            case 1: s.add(new Square()); break;
            case 2: s.add(new Triangle()); break;
            default:
        }
    }
    @Override
    public Iterator<Shape> iterator() {
        return new Iterator<>() {
            private int index = 0;
            @Override
            public boolean hasNext() { return index < count;}
            @Override
            public Shape next() { return s.get(index++);}
        };
    }
}

适配器方法惯用法

适配器方法,提供特定接口满足需求,即对一个方法,有不同的具体需求。

public class MultiIterableClass extends IterableClass {
    public Iterable<String> reversed() {
        // 不同的具体实现,但返回类型仍然是Iterator
        return () -> new Iterator<>() {
            int current = words.length - 1;
            @Override
            public boolean hasNext() { return current > -1; }
            @Override
            public String next() { return words[current--]; }
            @Override
            public void remove() { throw new UnsupportedOperationException();}
        };
    }
    public Iterable<String> randomized() {
        // 不同的具体实现,但返回类型仍然是Iterator
        return () -> {
            List<String> shuffled =
                    new ArrayList<>(Arrays.asList(words));
            Collections.shuffle(shuffled, new Random());
            return shuffled.iterator();  // 返回类型仍然是iterator
        };
    }
    public static void main(String[] args) {
        var mic = new MultiIterableClass();
        for (String s : mic.reversed()) print(s + " ");
        println();
        for (String s : mic.randomized()) print(s + " ");
        println();
        for (String s : mic) print(s + " ");
    }
}

总结

Collection和Map是容器类库中的两种主要类型,区别在于容器中每个槽保存的元素个数

  • Collection在每个槽中只能保存一个元素:
    • List: 以特定的顺序保存一组元素;
      • ArrayList & LinkedList按插入顺序输出,都是排好序的
    • Set: 元素不能重复;
      • HashSet: 排序无实际意义,但获取速度最快;
      • TreeSet: 按照一定顺序排序,保持元素处于排序状态;
      • LinkedHashSet: 按元素被添加的顺序保存对象
    • Queue: 只允许在容器一端插入,并从另一段移除。
      • PriorityQueue: 优先级队列;
  • Map每个槽可以保存两个元素:即键值 。
    • HashMap: 排序无实际意义,但获取速度最快;
    • TreeMap: 按照一定顺序排序,保持键处于排序状态;
    • LinkedHashMap: 按元素被添加的顺序保存对象,速度也很快。
      Map 和 Collection的重叠就是Map可以使用entrySet()和values()来产生Collection。
public class Test {
    public static void main(String[] args) {
        var m = new LinkedHashMap<Integer, Integer>();
        m.put(1, 2);
        m.put(2, 4);
        List<Map.Entry<Integer, Integer>> me = new LinkedList<>(m.entrySet());
        println(m);  // {1=2, 2=4}
        println(me);  // [1=2, 2=4]
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值