StringArraySet.java

  1. /*
  2.  ***** BEGIN LICENSE BLOCK *****
  3.  * Version: EPL 1.0/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Eclipse Public
  6.  * License Version 1.0 (the "License"); you may not use this file
  7.  * except in compliance with the License. You may obtain a copy of
  8.  * the License at http://www.eclipse.org/legal/epl-v10.html
  9.  *
  10.  * Software distributed under the License is distributed on an "AS
  11.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  12.  * implied. See the License for the specific language governing
  13.  * rights and limitations under the License.
  14.  *
  15.  * Copyright (C) 2011 Charles O Nutter <headius@headius.com>
  16.  *
  17.  * Alternatively, the contents of this file may be used under the terms of
  18.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  19.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  20.  * in which case the provisions of the GPL or the LGPL are applicable instead
  21.  * of those above. If you wish to allow use of your version of this file only
  22.  * under the terms of either the GPL or the LGPL, and not to allow others to
  23.  * use your version of this file under the terms of the EPL, indicate your
  24.  * decision by deleting the provisions above and replace them with the notice
  25.  * and other provisions required by the GPL or the LGPL. If you do not delete
  26.  * the provisions above, a recipient may use your version of this file under
  27.  * the terms of any one of the EPL, the GPL or the LGPL.
  28.  ***** END LICENSE BLOCK *****/
  29. package org.jruby.util.collections;

  30. import java.util.HashSet;
  31. import java.util.Set;
  32. import org.jruby.Ruby;
  33. import org.jruby.RubyArray;
  34. import org.jruby.RubyBoolean;
  35. import org.jruby.runtime.Block;
  36. import org.jruby.runtime.ThreadContext;
  37. import org.jruby.runtime.builtin.IRubyObject;

  38. /**
  39.  * An RubyArray that maintains an O(1) Set for fast include? operations.
  40.  */
  41. public class StringArraySet extends RubyArray {
  42.     private final Set<String> set = new HashSet<String>();

  43.     public StringArraySet(Ruby runtime) {
  44.         super(runtime, 4);
  45.     }

  46.     @Override
  47.     public synchronized RubyArray append(IRubyObject item) {
  48.         String string = getStringFromItem(item);
  49.         RubyArray result = super.append(item);
  50.         set.add(string);
  51.         return result;
  52.     }

  53.     @Override
  54.     public synchronized void clear() {
  55.         super.clear();
  56.         set.clear();
  57.     }

  58.     @Override
  59.     public synchronized IRubyObject delete(ThreadContext context, IRubyObject item, Block block) {
  60.         String string = getStringFromItem(item);
  61.         IRubyObject result = super.delete(context, item, block);
  62.         set.remove(string);
  63.         return result;
  64.     }

  65.     @Override
  66.     public synchronized IRubyObject delete_if(ThreadContext context, Block block) {
  67.         IRubyObject result = super.delete_if(context, block);
  68.         rehash();
  69.         return result;
  70.     }

  71.     @Override
  72.     public synchronized RubyBoolean include_p(ThreadContext context, IRubyObject item) {
  73.         return context.runtime.newBoolean(set.contains(getStringFromItem(item)));
  74.     }

  75.     @Override
  76.     public synchronized IRubyObject replace(IRubyObject orig) {
  77.         IRubyObject result = super.replace(orig);
  78.         rehash();
  79.         return result;
  80.     }

  81.     @Override
  82.     public synchronized IRubyObject unshift(IRubyObject item) {
  83.         String string = getStringFromItem(item);
  84.         IRubyObject result = super.unshift(item);
  85.         set.add(string);
  86.         return result;
  87.     }

  88.     @Override
  89.     public synchronized IRubyObject unshift(IRubyObject[] items) {
  90.         IRubyObject result = super.unshift(items);
  91.         putAll(toJavaArray());
  92.         return result;
  93.     }

  94.     @Override
  95.     public synchronized IRubyObject aset(IRubyObject arg0, IRubyObject arg1) {
  96.         IRubyObject result = super.aset(arg0, arg1);
  97.         rehash();
  98.         return result;
  99.     }

  100.     @Override
  101.     public synchronized IRubyObject aset(IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
  102.         IRubyObject result = super.aset(arg0, arg1, arg2);
  103.         rehash();
  104.         return result;
  105.     }

  106.     @Override
  107.     public synchronized IRubyObject aset19(IRubyObject arg0, IRubyObject arg1) {
  108.         IRubyObject result = super.aset19(arg0, arg1);
  109.         rehash();
  110.         return result;
  111.     }

  112.     @Override
  113.     public synchronized RubyArray collectBang(ThreadContext context, Block block) {
  114.         RubyArray result = super.collectBang(context, block);
  115.         rehash();
  116.         return result;
  117.     }

  118.     @Override
  119.     public synchronized IRubyObject collect_bang(ThreadContext context, Block block) {
  120.         IRubyObject result = super.collect_bang(context, block);
  121.         rehash();
  122.         return result;
  123.     }

  124.     @Override
  125.     public synchronized IRubyObject compact() {
  126.         IRubyObject result = super.compact();
  127.         rehash();
  128.         return result;
  129.     }

  130.     @Override
  131.     public synchronized IRubyObject drop(ThreadContext context, IRubyObject n) {
  132.         IRubyObject result = super.drop(context, n);
  133.         rehash();
  134.         return result;
  135.     }

  136.     @Override
  137.     public synchronized IRubyObject drop_while(ThreadContext context, Block block) {
  138.         IRubyObject result = super.drop_while(context, block);
  139.         rehash();
  140.         return result;
  141.     }

  142.     @Override
  143.     public synchronized IRubyObject flatten_bang(ThreadContext context) {
  144.         IRubyObject result = super.flatten_bang(context);
  145.         rehash();
  146.         return result;
  147.     }

  148.     @Override
  149.     public synchronized IRubyObject flatten_bang(ThreadContext context, IRubyObject arg) {
  150.         IRubyObject result = super.flatten_bang(context, arg);
  151.         rehash();
  152.         return result;
  153.     }

  154.     @Override
  155.     public synchronized IRubyObject flatten_bang19(ThreadContext context) {
  156.         IRubyObject result = super.flatten_bang19(context);
  157.         rehash();
  158.         return result;
  159.     }

  160.     @Override
  161.     public synchronized IRubyObject flatten_bang19(ThreadContext context, IRubyObject arg) {
  162.         IRubyObject result = super.flatten_bang19(context, arg);
  163.         rehash();
  164.         return result;
  165.     }

  166.     @Override
  167.     public synchronized IRubyObject insert() {
  168.         IRubyObject result = super.insert();
  169.         rehash();
  170.         return result;
  171.     }

  172.     @Override
  173.     public synchronized IRubyObject insert(IRubyObject arg) {
  174.         IRubyObject result = super.insert(arg);
  175.         rehash();
  176.         return result;
  177.     }

  178.     @Override
  179.     public synchronized IRubyObject insert(IRubyObject arg1, IRubyObject arg2) {
  180.         IRubyObject result = super.insert(arg1, arg2);
  181.         rehash();
  182.         return result;
  183.     }

  184.     @Override
  185.     public synchronized IRubyObject insert(IRubyObject[] args) {
  186.         IRubyObject result = super.insert(args);
  187.         rehash();
  188.         return result;
  189.     }

  190.     @Override
  191.     public synchronized IRubyObject insert19(IRubyObject arg) {
  192.         IRubyObject result = super.insert19(arg);
  193.         rehash();
  194.         return result;
  195.     }

  196.     @Override
  197.     public synchronized IRubyObject insert19(IRubyObject arg1, IRubyObject arg2) {
  198.         IRubyObject result = super.insert19(arg1, arg2);
  199.         rehash();
  200.         return result;
  201.     }

  202.     @Override
  203.     public synchronized IRubyObject insert19(IRubyObject[] args) {
  204.         IRubyObject result = super.insert19(args);
  205.         rehash();
  206.         return result;
  207.     }

  208.     @Override
  209.     public synchronized IRubyObject map_bang(ThreadContext context, Block block) {
  210.         IRubyObject result = super.map_bang(context, block);
  211.         rehash();
  212.         return result;
  213.     }

  214.     @Override
  215.     public synchronized IRubyObject pop(ThreadContext context) {
  216.         IRubyObject result = super.pop(context);
  217.         rehash();
  218.         return result;
  219.     }

  220.     @Override
  221.     public synchronized IRubyObject pop(ThreadContext context, IRubyObject num) {
  222.         IRubyObject result = super.pop(context, num);
  223.         rehash();
  224.         return result;
  225.     }

  226.     @Override
  227.     public synchronized RubyArray push_m(IRubyObject[] items) {
  228.         RubyArray result = super.push_m(items);
  229.         rehash();
  230.         return result;
  231.     }

  232.     @Override
  233.     public synchronized RubyArray push_m19(IRubyObject[] items) {
  234.         RubyArray result = super.push_m19(items);
  235.         rehash();
  236.         return result;
  237.     }

  238.     @Override
  239.     public synchronized IRubyObject rejectBang(ThreadContext context, Block block) {
  240.         IRubyObject result = super.rejectBang(context, block);
  241.         rehash();
  242.         return result;
  243.     }

  244.     @Override
  245.     public synchronized IRubyObject reject_bang(ThreadContext context, Block block) {
  246.         IRubyObject result = super.reject_bang(context, block);
  247.         rehash();
  248.         return result;
  249.     }

  250.     @Override
  251.     public synchronized IRubyObject select_bang(ThreadContext context, Block block) {
  252.         IRubyObject result = super.select_bang(context, block);
  253.         rehash();
  254.         return result;
  255.     }

  256.     @Override
  257.     public synchronized IRubyObject shift(ThreadContext context) {
  258.         IRubyObject result = super.shift(context);
  259.         rehash();
  260.         return result;
  261.     }

  262.     @Override
  263.     public synchronized IRubyObject shift(ThreadContext context, IRubyObject num) {
  264.         IRubyObject result = super.shift(context, num);
  265.         rehash();
  266.         return result;
  267.     }

  268.     @Override
  269.     public synchronized IRubyObject slice_bang(IRubyObject arg0) {
  270.         IRubyObject result = super.slice_bang(arg0);
  271.         rehash();
  272.         return result;
  273.     }

  274.     @Override
  275.     public synchronized IRubyObject slice_bang(IRubyObject arg0, IRubyObject arg1) {
  276.         IRubyObject result = super.slice_bang(arg0, arg1);
  277.         rehash();
  278.         return result;
  279.     }

  280.     @Override
  281.     public synchronized IRubyObject unshift() {
  282.         IRubyObject result = super.unshift();
  283.         rehash();
  284.         return result;
  285.     }

  286.     @Override
  287.     public synchronized IRubyObject unshift19() {
  288.         IRubyObject result = super.unshift19();
  289.         rehash();
  290.         return result;
  291.     }

  292.     @Override
  293.     public synchronized IRubyObject unshift19(IRubyObject item) {
  294.         IRubyObject result = super.unshift19(item);
  295.         rehash();
  296.         return result;
  297.     }

  298.     public synchronized boolean containsString(String element) {
  299.         return set.contains(element);
  300.     }

  301.     private String getStringFromItem(IRubyObject item) {
  302.         return item.convertToString().asJavaString();
  303.     }

  304.     private void rehash() {
  305.         set.clear();
  306.         putAll(toJavaArray());
  307.     }

  308.     private void putAll(IRubyObject[] items) {
  309.         for (IRubyObject item : items) {
  310.             String string = getStringFromItem(item);
  311.             set.add(string);
  312.         }
  313.     }
  314.    
  315. }