【问题标题】:How to pass only 1 element to ArrayAdapter and make sure it only displays unique items如何仅将 1 个元素传递给 ArrayAdapter 并确保它仅显示唯一项目
【发布时间】:2020-03-24 12:12:43
【问题描述】:

希望我的问题是有道理的。

在一个项目上工作并且试图使用自定义ArrayAdapter 来只显示一个类中的唯一元素时遇到了心理障碍。我创建了一个由 3 个字符串组成的类。歌曲名称、类别和艺术家。

我在我的MainActivity 中创建了一个ArrayList。我想在一些不同的活动中使用ArrayList。我已经能够在我创建的 ArrayAdapter 中使用它,它在 TextViews 中显示所有 3 个字段,但我想为仅显示其中一个字段而不显示的不同活动创建另一个 ArrayAdapter显示重复项。因此,例如,ArrayAdapter 仅提供 Category 元素并仅显示唯一元素。

我很难思考如何仅将 1 个元素从 ArrayList 传递到 ArrayAdapter 并确保它不显示重复项。

对 android 开发相当陌生,无法找到答案,所以如果你能帮助我或指出正确的方向,我将不胜感激。

编辑答案:通过添加以下内容能够使其工作:

        ArrayList<Music> Library = MainActivity.music;


        ArrayList<String> artists = new ArrayList<String>();

        Log.i("MainActivity", String.valueOf(Library.size()));
        for (int i = 0; i<Library.size(); i++){
            String artist = Library.get(i).getArtist();
            if (!artists.contains(artist))
            artists.add(artist);

            Log.i("MainActivity", "artist");
        } 

编辑:包括下面原始 ArrayList 的屏幕截图。正如你在我的想法中看到的,一些类别和艺术家会重复。我想创建一个只显示艺术家的活动和另一个只显示类别的活动。需要注意的是,我只希望显示唯一值而不是重复值并包括 github 链接。

github:https://github.com/Nimzr/Music-Player

【问题讨论】:

  • 如果你能分享一些你目前正在经历的截图以及一些相关代码,那就太好了。
  • 在我看来,您想要的只是简单地获取您想要的列表中的一项并将其放入 another ArrayList 中,然后可以将其传递给另一个 ArrayAdapter .
  • @SyedAhmedJamil 好点,我添加了一个屏幕截图,但请告诉我您希望我包含哪些代码,我会的。
  • @GabrielVasconcelos 我开始有同样的想法。我会试一试的。

标签: java android arrays arraylist collections


【解决方案1】:

您可以首先创建要查看的对象的修剪版本,然后创建一个方法实用程序,允许您根据参数化条件过滤掉原始List 的元素.留下的元素将它们映射到新的 trim 版本,并使用新的List 作为自定义ArrayAdapter 的源。以下是这个想法的骨架:

    public ArrayAdapter<TrimmedElement> createCustomArrayAdapter(
            Context context, List<WholeElement> target, Predicate<WholeElement> condition) {

        List<TrimmedElement> trimmedList = target.stream()
                .filter(condition)
                .map(TrimmedElement::new)
                .collect(Collectors.toList());

        return new MyCustomArrayAdapter<TrimmedElement>(context, trimmedList);
    }

    static class WholeElement {}
    static class TrimmedElement {
        public TrimmedElement(WholeElement ele) {
            // Copy the information desired
        }
    }

Complete code on GitHub

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    默认情况下,ArrayAdapter 将为您的ArrayList 中的每个数组项创建视图。要自定义 ArrayAdapter 如何为您的数据创建视图,您需要扩展它并覆盖其 getView() 方法并为每个项目使用不同的布局,就像这样

    注意: 我假设 Music 是具有这 3 个字符串的类,并且您创建了一个名为 unique_layout.xml 的新布局,它只有一个 TextView显示一个你这些字符串。

    public class CustomArrayAdapter extends ArrayAdapter<Music> {
        public CustomArrayAdapter(Context context, ArrayList<Music> musicList) {
           super(context, 0, users);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
    
           Music music = getItem(position); 
    
           // Here use that new layout that you created 
           if (convertView == null) {
              convertView = LayoutInflater.from(getContext()).inflate(R.layout.unique_layout, parent, false);
           }
    
           // Assign text to the TextView from that new layout
           TextView category = (TextView) convertView.findViewById(R.id.category);
           category.setText(music.category);
    
           return convertView;
       }
    }
    

    更新:从 ArrayList 中删除重复项

    注意:以下方法会删除重复项并将结果列表放入新的ArrayList&lt;String&gt;,您可以将其用作ArrayAdapter 的来源。所以你现在不必扩展ArrayAdapter

    ArrayList中删除重复项的常用方法有3种

    1. 手动操作(祝你好运)
    2. 使用Streams (仅适用于 API 24:牛轧糖及更高版本)
    3. 使用LinkedHashSet (从 API 1 开始可用)

    假设您有如下定义的数组列表

    ArrayList<Music> musicList = new ArrayList<>();
    ArrayList<String> categoryList = new ArrayList<>();
    
    musicList.add(new Music("song1", "category1", "artist1"));
    musicList.add(new Music("song2", "category2", "artist2"));
    musicList.add(new Music("song3", "category3", "artist3"));
    musicList.add(new Music("song4", "category2", "artist4"));
    musicList.add(new Music("song5", "category1", "artist1"));
    musicList.add(new Music("song6", "category4", "artist5"));
    musicList.add(new Music("song7", "category3", "artist2"));
    

    选项 2:使用Streams

    我在这里所做的是使用map() 方法仅提取category 字段并使用distinct() 方法删除重复项,然后最终将所有这些修改收集到categoryList 中。如果你需要提取独特的艺术家,只需将music.category更改为music.artist

    EZ!

    注意:map() 方法之后,我们现在正在处理字符串数组,因此 distinct() 使用 equals()hashCode() 方法987654349@ 类查找和删除重复项。如果您在 musicList 上直接使用 distinct(),它是 Music 类的数组,那么您的 Music 类应该覆盖并提供 equals()hashCode() 方法的实现。

    阅读更多关于他们的信息herehere

    categoryList = musicList.stream()
                  .map((music)-> music.category)
                  .distinct()
                  .collect(Collectors.toCollection(ArrayList::new));
    
    Log.d("CATEGORY LIST" ,  categoryList.toString())
    
    //LOG Output 
    CATEGORY LIST: [category1, category2, category3, category4]
    

    选项 3:使用LinkedHashSet

    这个方法比较简单。和之前一样,首先提取category 字段并将它们存储到categoryList。创建LinkedHashSet 将自动删除重复值,就像使用流时的distinct() 方法一样。之后只需清除 categoryList 并使用哈希集中的唯一值对其进行更新。

    musicList.forEach((music) -> {
        categoryList.add(music.category);
    });
    
    LinkedHashSet<String> uniqueCategoryHashSet = new LinkedHashSet(categoryList);
    
    categoryList.clear();
    categoryList.addAll(uniqueCategoryHashSet);
    
    Log.d("CATEGORY LIST" ,  categoryList.toString())
    
    //LOG Output 
    CATEGORY LIST: [category1, category2, category3, category4]
    

    现在我绝不会将 选项 3 标记为有效的解决方案。如果由于 API 限制而无法使用流,也许您可​​以手动执行此操作会更好。但这可以完成工作。

    【讨论】:

    • 这对我来说很有意义,但如果 ArrayList 包含重复的类别,它仍然会显示重复项,不是吗?
    • 那么在这种情况下,快速的解决方案是使用 streams 从您当前的 ArrayList 创建一个临时的新 ArrayList 并删除具有相同类别(或您关注的任何领域)的条目和将其传递给您的自定义数组适配器。 Streams 是一个 java 8 概念,因此请确保您的 android studio 使用的是 java 8 而不是 java 7。我稍后会提出一个适当的解决方案,同时您可以看到 @Macro R 的答案,它也使用了流
    • 我通过添加这个得到了它,我正用头撞墙,试图理解有意义的流,但试图了解我如何工作却很困难。让我知道我的方法是否是个坏主意。 ` ArrayList 库 = MainActivity.music; ArrayList 艺术家 = new ArrayList(); for (int i = 0; icode 为上面的代码工作。
    • 很难阅读您在 cmets 中的代码 :) 但是是的,您的方法很正常。 "can't get the code thing to work" 是什么意思?你在说哪个代码?无论如何抱歉迟到的答案,但我已经用不同的解决方案更新了我的答案,关于如何删除重复项。检查一下。希望这能回答你的问题
    • 哦,你没有什么好遗憾的,当我说我无法让代码工作时,我的意思是代码块没有在评论中正确显示。就这样。你帮了大忙!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多