通用类型:如何从通用类型数组中获取最常见的字符

时间:2015-04-03 20:13:58

标签: java arrays generics

我正在与ArrayLists斗争,我的方法public static <T> Pair<T, Integer> mode(T items[])必须返回最常见的字符(或String,或Integer,或Double)以及在数组中遇到的次数。假设new String[]{"a","b","a"},方法应该返回"a", 2。或者,另一个示例,new Integer[]{30,10,10,20}应该返回10, 2(数组10中的数字10会被满足)。请有人指导我到正确的轨道?考虑到我不允许使用地图,收藏......只有ArrayLists!

 import java.util.ArrayList;

public class Mode {

    public static <T> Pair<T, Integer> mode(T items[])
    {
        ArrayList<T> trackItems = new ArrayList<>();

        for(T values: items)
        {
            trackItems.add(values);
        }

        for(int i = 0; i < trackItems.size(); i++)
        {
            int count = (Integer)trackItems.get(i);
        }

    }
}
    public class Pair<X,Y>{
      private X first;
      private Y second;

      public Pair(X x, Y y){
        this.first = x;
        this.second = y;
      }

      public X getFirst(){
        return this.first;
      }
      public Y getSecond(){
        return this.second;
      }

      public boolean equals(Object o){
        if(!(o instanceof Pair)){
          return false;
        }
        Pair p = (Pair) o;
        return
          this.first.equals(p.first) &&
          this.second.equals(p.second);
      }

      public String toString(){
        return String.format("(%s,%s)",first,second);
      }

    }

3 个答案:

答案 0 :(得分:0)

为什么不使用您Pair类的数组列表来模拟地图。

使类型X与您要匹配的类型相同,并键入Y一个int。 first代表字符,Y代表字符发生的次数。

  • 制作ArrayList Pair
  • 遍历您的源列表,并在每次迭代时,搜索新的ArrayList,查找first等于您当前元素的元素。
  • 如果找到,请在second元素中添加1。
  • 如果您找不到,请添加一个,将second元素初始化为1。

答案 1 :(得分:0)

假设您使用此答案来理解如何处理此类问题,并且如果是这种情况,则不要公开复制答案以完成作业。

由于Pair类的第二个参数仅为Integer,因此为了简单起见,我将其定义如下:

public class Pair<T>
{
  private T value;
  private int count;

  public Pair (T value, int count)
  {
    this.value = value;
    this.count = count;
  }

  @Override
  public String toString ()
  {
    return String.format ("Pair: [%s, %s]", value, count);
  }
}

现在,Mode类:

import java.util.ArrayList;
import java.util.Comparator;

public class Mode
{
  public static <T extends Comparable> Pair<T> mode (ArrayList<T> items) throws Exception
  {
    if (items == null)
    {
      throw new NullPointerException ("Items Can't be Null");
    }
    else if (items.size () == 0)
    {
      throw new Exception ("Items needs to be more than 0");
    }

    items.sort (Comparator.<T>naturalOrder ());

    int maxCount = 1;
    int itemCount = 0;

    T maxItem = items.get (0);
    T currentItem = items.get (0);

    for (T item : items)
    {
      if (item.equals (currentItem))
      {
        itemCount++;
      }
      else if (itemCount > maxCount)
      {
        maxCount = itemCount;
        itemCount = 0;

        maxItem = currentItem;
        currentItem = item;
      }
    }

    return new Pair<T> (maxItem, maxCount);
  }
}

在此,我使用T行确保ComparableT extends Comparable。这样做是为了可以使用排序方法对ArrayList<T>进行排序。

接下来,在mode函数中,我首先检查ArrayList<T> itemsnull还是0项。如果是这种情况,我会抛出适当的例外。

接下来我对items进行排序。因此,如果ArrayList属于Integer且项目为10, 20, 10,那么在排序后它将为10, 10, 20

然后我假设具有最大计数的元素是第一个元素。

在此之后,我遍历项目以查看下一个项目是否等于上一个项目。如果是,我增加itemCount。如果不是,我会检查maxCount是否小于itemCount。如果是这种情况,请更新我的maxItemcurrentItemmaxCount,然后重置itemCount并重复此过程。

循环结束后,我会在maxItem中拥有频率最高的值,maxCount将保持该频率。

以下是一个示例测试来演示它:

import java.util.ArrayList;
import java.util.Arrays;

public class Main
{
  public static void main (String[] args) throws Exception
  {
    ArrayList<Integer> integers = new ArrayList<> (Arrays.asList (10, 20, 10));
    System.out.println (Mode.mode (integers));

    ArrayList<String> strings = new ArrayList<> (Arrays.asList ("a", "b", "a", "a"));
    System.out.println (Mode.mode (strings));
  }
}

输出结果为:
Pair: [10, 2]
Pair: [a, 3]

除非我把你的问题读错了,否则这是预期的。

答案 2 :(得分:0)

这里是一个(1,虽然很长,线)解决方案,它不使用任何对象,只是方法:

public static <T> Pair<T, Integer> mode(T[] items) {
    return Arrays.stream(items)
      .collect(Collectors.groupingBy(o -> o, Collectors.counting()))
      .entrySet().stream()
      .sorted((a, b) -> b.getValue() - a.getValue())
      .findFirst().get()
      .map(e -> new Pair(e.getKey(), e.getValue());
}