使方法对 CharSequence[] 和 Set<String> 通用

Make method generic to CharSequence[] and Set<String>

我正在尝试将方法转换为 CharSequence[] 和 Set 的通用方法。嗯,我没有这方面的经验。

这是第二个 argument/return 值应该是泛型 (T) 的方法。可能吗?

private CharSequence[] remove(String string, CharSequence[] charSequences)
    {
        ArrayList<CharSequence> newArray = new ArrayList<CharSequence>();
        int foundPlace = -1;
        CharSequence[] v = charSequences;
        for (int i = 0; i < v.length; i++) {
            if (foundPlace != -1 && v[i].equals(string))
                foundPlace = i;
            else
                newArray.add(v[i]);
        }
        return newArray.toArray(new CharSequence[newArray.size()]);
    }

我试过的。替换了 T 出现 CharSequence[] 的所有地方,但是当我将 T 放在 T.length.

行时它不起作用

更多说明(抱歉)。我想将第二个参数和 return 值转换为 T - 所以到处都是 CharSequence[] 到 T.

泛型和数组可能是一个非常痛苦的组合。我会坚持使用 List 界面,如果这对您来说是一个选项(即,将 return 类型更改为 List 并简单地将 return newArray 也属于 List 类型)。

否则我推荐这个 post 以更好地理解泛型和数组: How to create a generic array in Java?

编辑:哦,你绝对不想用 "T" 替换 "CharSequence[]",但如果你真的需要在这里使用数组,可以用 "T[]" 替换。

要实现通用集合,请使用:

int length; // ...
T[] array = (T[])new Object[length];

因此,return 语句将如下所示:

return (T[])newArray.toArray(new Object[newArray.size()]);
  • 您对 foundPlace 使用了一个整数,但是一个布尔值就足够了,因为您只是测试它是否已被初始化并且从不使用它的值。
  • 你甚至不需要这个布尔值,你的 equals 测试永远不会被评估,因为 ̀foundPlace 总是等于 -1(所以你的数组 return 是总是 charSequences)
  • 的副本
  • 你不需要中间变量v,你可以简单地遍历charSequences

这是一个带有 Object 的版本,如果它是您要找的:

private Object[] remove(Object val, Object[] array)
    {
        ArrayList<Object> newArray = new ArrayList<Object>();
        for (Object o : array)
            if(!o.equals(val))
                newArray.add(o);
        return newArray.toArray(new Object[newArray.size()]);
}

以下是实现删除例程的方法。请注意,您甚至不需要单独的删除方法。希望我没有遗漏需要您创建单独的删除方法的用例。

package com.anupam;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class SO31535852 {
  public static void main(String args[]) {
    String[] arr = {"1", "2", "3"};

    // Create a copy of the orginal array if you do not want to modify it.
    Set<String> test = new HashSet<>(Arrays.asList(Arrays.copyOf(arr, arr.length)));

    // In fact you do not even need a remove method. I could not understand why you are using
    // foundPlace variable it's not doing much.
    System.out.println(remove("1", test));
    System.out.println(remove("1", test));
  }

  /**
   * Removes a specific value from the underling collection
   *
   * @param toRemove the object to be removed
   * @param myCollection the colelction from which to be removed
   * @return the removed value or null.
   */
  private static <T> T remove(T toRemove, Set<T> myCollection) {
    return myCollection.remove(toRemove) ? toRemove : null;
  }
}

也许这就是您想要的:

private <T> T[] remove(T string, T[] charSequences)
    {
        ArrayList<T> newArray = new ArrayList<T>();
        int foundPlace = -1;
        T[] v = charSequences;
        for (int i = 0; i < v.length; i++) {
            if (foundPlace != -1 && v[i].equals(string))
                foundPlace = i;
            else
                newArray.add(v[i]);
        }
        @SuppressWarnings("unchecked")
        T[] ret = (T[]) Array.newInstance(v.getClass().getComponentType(), newArray.size());
        return newArray.toArray(ret);
    }

或者,如果包含的 class 也应该是类型 T 的泛型,只需从上面删除 <T>。所以这一行,

private <T> T[] remove(T string, T[] charSequences)

然后会变成,

private T[] remove(T string, T[] charSequences)

如果 string 的类型无关紧要,您可以将其类型更改为普通的 Object

private T[] remove(Object string, T[] charSequences)
    {
        ArrayList<T> newArray = new ArrayList<T>();
        int foundPlace = -1;
        T[] v = charSequences;
        for (int i = 0; i < v.length; i++) {
            if (foundPlace != -1 && v[i].equals(string))
                foundPlace = i;
            else
                newArray.add(v[i]);
        }
        ...
    }

之后您可能还想将 string 重命名为其他名称。


我还应该注意到,在您的逻辑中,foundPlace 将始终是 -1