code: private List<IAtom> selectIons(IAtomContainer frag, int sign) {
          int fragChg = frag.getProperty(FRAGMENT_CHARGE);
          assert Integer.signum(fragChg) == sign;
          final List<IAtom> atoms = new ArrayList<>();
  
          FIRST_PASS:
          for (IAtom atom : frag.atoms()) {
              if (fragChg == 0)
                  break;
              int atmChg = nullAsZero(atom.getFormalCharge());
              if (Integer.signum(atmChg) == sign) {
  
                  // skip in first pass if charge separated
                  for (IBond bond : frag.getConnectedBondsList(atom)) {
                      if (Integer.signum(nullAsZero(bond.getOther(atom).getFormalCharge())) + sign == 0)
                          continue FIRST_PASS;
                  }
  
                  while (fragChg != 0 && atmChg != 0) {
                      atoms.add(atom);
                      atmChg -= sign;
                      fragChg -= sign;
                  }
              }
          }
  
          if (fragChg == 0)
              return atoms;
  
          for (IAtom atom : frag.atoms()) {
              if (fragChg == 0)
                  break;
              int atmChg = nullAsZero(atom.getFormalCharge());
              if (Math.signum(atmChg) == sign) {
                  while (fragChg != 0 && atmChg != 0) {
                      atoms.add(atom);
                      atmChg -= sign;
                      fragChg -= sign;
                  }
              }
          }
  
          return atoms;
      }
docs: Select ions from a charged fragment. Ions not in charge separated
  bonds are favoured but select if needed. If an atom has lost or
  gained more than one electron it is added mutliple times to the
  output list
  
  @param frag charged fragment
  @param sign the charge sign to select (+1 : cation, -1: anion)
  @return the select atoms (includes duplicates)