Каков семантический способ установки логического свойства объекта? [Дубликат]

В общем, подход, предложенный CaseyB , отлично работает, на самом деле, если вы проходите в List, трудно его винить, возможно, я бы изменил его на:

public static IEnumerable> ChunkTrivialBetter(this IEnumerable source, int chunksize)
{
   var pos = 0; 
   while (source.Skip(pos).Any())
   {
      yield return source.Skip(pos).Take(chunksize);
      pos += chunksize;
   }
}

Это позволит избежать массовых цепочек вызовов. Тем не менее, этот подход имеет общий недостаток. Он материализует два перечисления на кусок, чтобы подчеркнуть проблему:

foreach (var item in Enumerable.Range(1, int.MaxValue).Chunk(8).Skip(100000).First())
{
   Console.WriteLine(item);
}
// wait forever 

Чтобы преодолеть это, мы можем попробовать подход Кэмерона , который проходит вышеупомянутый тест в летающих цветах, поскольку он только перебирает перечисление один раз.

Проблема в том, что у него есть другой недостаток, он материализует каждый элемент в каждом фрагменте, проблема с этим подходом заключается в том, что вы работаете высоко в памяти.

Чтобы проиллюстрировать эту попытку:

foreach (var item in Enumerable.Range(1, int.MaxValue)
               .Select(x => x + new string('x', 100000))
               .Clump(10000).Skip(100).First())
{
   Console.Write('.');
}
// OutOfMemoryException

Наконец, любая реализация должна иметь возможность обрабатывать итерацию кусков, например:

Enumerable.Range(1,3).Chunk(2).Reverse().ToArray()
// should return [3],[1,2]

Многие очень оптимальные решения, такие как моя первая версия этого ответа, не удалось. Такую же проблему можно найти в answer.One оптимизированный ответ .

Чтобы решить все эти проблемы, вы можете использовать следующее:

namespace ChunkedEnumerator
{
    public static class Extensions 
    {
        class ChunkedEnumerable : IEnumerable
        {
            class ChildEnumerator : IEnumerator
            {
                ChunkedEnumerable parent;
                int position;
                bool done = false;
                T current;


                public ChildEnumerator(ChunkedEnumerable parent)
                {
                    this.parent = parent;
                    position = -1;
                    parent.wrapper.AddRef();
                }

                public T Current
                {
                    get
                    {
                        if (position == -1 || done)
                        {
                            throw new InvalidOperationException();
                        }
                        return current;

                    }
                }

                public void Dispose()
                {
                    if (!done)
                    {
                        done = true;
                        parent.wrapper.RemoveRef();
                    }
                }

                object System.Collections.IEnumerator.Current
                {
                    get { return Current; }
                }

                public bool MoveNext()
                {
                    position++;

                    if (position + 1 > parent.chunkSize)
                    {
                        done = true;
                    }

                    if (!done)
                    {
                        done = !parent.wrapper.Get(position + parent.start, out current);
                    }

                    return !done;

                }

                public void Reset()
                {
                    // per http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx
                    throw new NotSupportedException();
                }
            }

            EnumeratorWrapper wrapper;
            int chunkSize;
            int start;

            public ChunkedEnumerable(EnumeratorWrapper wrapper, int chunkSize, int start)
            {
                this.wrapper = wrapper;
                this.chunkSize = chunkSize;
                this.start = start;
            }

            public IEnumerator GetEnumerator()
            {
                return new ChildEnumerator(this);
            }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }

        }

        class EnumeratorWrapper
        {
            public EnumeratorWrapper (IEnumerable source)
            {
                SourceEumerable = source;
            }
            IEnumerable SourceEumerable {get; set;}

            Enumeration currentEnumeration;

            class Enumeration
            {
                public IEnumerator Source { get; set; }
                public int Position { get; set; }
                public bool AtEnd { get; set; }
            }

            public bool Get(int pos, out T item) 
            {

                if (currentEnumeration != null && currentEnumeration.Position > pos)
                {
                    currentEnumeration.Source.Dispose();
                    currentEnumeration = null;
                }

                if (currentEnumeration == null)
                {
                    currentEnumeration = new Enumeration { Position = -1, Source = SourceEumerable.GetEnumerator(), AtEnd = false };
                }

                item = default(T);
                if (currentEnumeration.AtEnd)
                {
                    return false;
                }

                while(currentEnumeration.Position < pos) 
                {
                    currentEnumeration.AtEnd = !currentEnumeration.Source.MoveNext();
                    currentEnumeration.Position++;

                    if (currentEnumeration.AtEnd) 
                    {
                        return false;
                    }

                }

                item = currentEnumeration.Source.Current;

                return true;
            }

            int refs = 0;

            // needed for dispose semantics 
            public void AddRef()
            {
                refs++;
            }

            public void RemoveRef()
            {
                refs--;
                if (refs == 0 && currentEnumeration != null)
                {
                    var copy = currentEnumeration;
                    currentEnumeration = null;
                    copy.Source.Dispose();
                }
            }
        }

        public static IEnumerable> Chunk(this IEnumerable source, int chunksize)
        {
            if (chunksize < 1) throw new InvalidOperationException();

            var wrapper =  new EnumeratorWrapper(source);

            int currentPos = 0;
            T ignore;
            try
            {
                wrapper.AddRef();
                while (wrapper.Get(currentPos, out ignore))
                {
                    yield return new ChunkedEnumerable(wrapper, chunksize, currentPos);
                    currentPos += chunksize;
                }
            }
            finally
            {
                wrapper.RemoveRef();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int i = 10;
            foreach (var group in Enumerable.Range(1, int.MaxValue).Skip(10000000).Chunk(3))
            {
                foreach (var n in group)
                {
                    Console.Write(n);
                    Console.Write(" ");
                }
                Console.WriteLine();
                if (i-- == 0) break;
            }


            var stuffs = Enumerable.Range(1, 10).Chunk(2).ToArray();

            foreach (var idx in new [] {3,2,1})
            {
                Console.Write("idx " + idx + " ");
                foreach (var n in stuffs[idx])
                {
                    Console.Write(n);
                    Console.Write(" ");
                }
                Console.WriteLine();
            }

            /*

10000001 10000002 10000003
10000004 10000005 10000006
10000007 10000008 10000009
10000010 10000011 10000012
10000013 10000014 10000015
10000016 10000017 10000018
10000019 10000020 10000021
10000022 10000023 10000024
10000025 10000026 10000027
10000028 10000029 10000030
10000031 10000032 10000033
idx 3 7 8
idx 2 5 6
idx 1 3 4
             */

            Console.ReadKey();


        }

    }
}

Существует также раунд оптимизаций, которые вы могли бы ввести для нестандартной итерации кусков, которая здесь отсутствует.

Каким образом вы должны выбрать? Это полностью зависит от проблемы, которую вы пытаетесь решить. Если вы не заинтересованы в первом недостатке, простой ответ невероятно привлекателен.

Обратите внимание, что как и в большинстве методов, это небезопасно для многопоточности, материал может стать странным, если вы хотите сделать его потокобезопасным необходимо будет исправить EnumeratorWrapper.

115
задан Tom Cammann 20 February 2013 в 18:18
поделиться

9 ответов

Предположим, что у вас есть

boolean active;

Метод аксессуаров будет

public boolean isActive(){return this.active;}

public void setActive(boolean active){this.active = active;}

См. также

174
ответ дан Jigar Joshi 21 August 2018 в 17:04
поделиться
  • 1
    Не могли бы вы указать раздел условных обозначений Sun, где конкретно описаны имена логических геттеров? Я не мог найти его. – Konstantin Pelepelin 29 March 2017 в 17:36
  • 2
    У меня есть boolean filed named hasCustomName. Теперь, что я должен назвать для методов getter и setter ? Хорошо ли setHasCustomName[setter] и hasCustomName[getter]? – Hadi 29 July 2018 в 08:50
  • 3
    тот же мой вопрос, что и @ Константин Пелепелин – Irfan Nasim 2 August 2018 в 11:31

Как установщик, как насчет:

// setter
public void beCurrent(boolean X) {
    this.isCurrent = X;
}

или

// setter
public void makeCurrent(boolean X) {
    this.isCurrent = X;
}

Я не уверен, что эти обозначения имеют смысл для носителей английского языка.

0
ответ дан amekusa 21 August 2018 в 17:04
поделиться

Чтобы избежать путаницы; Я рекомендую использовать

// Setter method for isCurrent

public void setIsCurrent(boolean isCurrent) {
    this.isCurrent = isCurrent;
}

// Getter method for isCurrent

public boolean getIsCurrent() {
    return isCurrent;
}
-8
ответ дан cello 21 August 2018 в 17:04
поделиться

Возможно, пришло время начать пересмотр этого ответа? Лично я проголосовал бы за setActive() и unsetActive() (альтернативы могут быть setUnActive(), notActive(), disable() и т. Д. В зависимости от контекста), поскольку «setActive» подразумевает, что вы активируете его в любое время, т. Это своего рода счетчик, интуитивно понятный, чтобы сказать «setActive», но фактически удалить активное состояние.

Другая проблема заключается в том, что вы не можете прослушивать специфическое событие SetActive в режиме CQRS, вам нужно будет прослушать 'setActiveEvent' и определить внутри этого прослушивателя, на самом деле он активен или нет. Или, конечно, определите, какое событие вызывать при вызове setActive(), но затем идет против принципа «Разделение проблем».

Хорошо читайте об этом в статье FlagArgument Мартина Фаулера: http: / /martinfowler.com/bliki/FlagArgument.html

Однако я исхожу из фона PHP и вижу, что эта тенденция все больше принимается. Не уверен, насколько это связано с развитием Java.

2
ответ дан Christian Vermeulen 21 August 2018 в 17:04
поделиться
4
ответ дан miku 21 August 2018 в 17:04
поделиться
private boolean current;

public void setCurrent(boolean current){
    this.current=current;
}

public boolean hasCurrent(){
    return this.current;
}
0
ответ дан Mkne 21 August 2018 в 17:04
поделиться
  • 1
    имеет текущий что? Я думаю, что has используется для BO или такой службы с некоторой обработкой, а для POJO - is. и, пожалуйста, добавьте описание вашего ответа. – Al-Mothafar 1 February 2018 в 09:48

http://geosoft.no/development/javastyle.html#Specific

  1. is следует использовать префикс для булевых переменных и методов. isSet, isVisible, isFinished, isFound, isOpen Это соглашение об именах для булевых методов и переменных, используемых Sun для базовых пакетов Java. Использование префикса решает общую проблему выбора плохих логических имен, таких как статус или флаг. isStatus или isFlag просто не подходит, и программист вынужден выбирать более значимые имена.

Методы сеттера для булевых переменных должны иметь префикс префикса, как в:

void setFound (boolean isFound); Есть несколько альтернатив префиксу, который лучше подходит в некоторых ситуациях. Они имеют, могут и должны иметь префиксы:

boolean hasLicense (); boolean canEvaluate (); boolean shouldAbort = false;

55
ответ дан rmtheis 21 August 2018 в 17:04
поделиться
  • 1
    +1 для альтернативных префиксов, которые очень важны (я нахожу) – Wolf 10 April 2014 в 15:35
  • 2
    Итак, если есть логическое свойство hasData, что бы выглядел сеттер? Скорее всего, setData(bool hasData) выглядит ужасно неправильным для меня ... – Franz B. 25 January 2016 в 10:34
  • 3
    @FranzB. Я бы использовал setHasData (...) – user362178 14 July 2016 в 01:05
  • 4
    Для тех, кто хочет следовать спецификации JavaBeans, кажется, что префиксы has, can, should не являются частью спецификации. Ссылка Спецификация JavaBeans 1.01 , раздел 8.3. – VCD 1 August 2016 в 07:16

Для поля с именем isCurrent правильное присвоение геттера / сеттера - setCurrent() / isCurrent() (по крайней мере, это то, что думает Eclipse), что очень сбивает с толку и может быть прослежено до основной проблемы:

В первую очередь ваше поле не должно называться isCurrent. Является ли глаголом, а глаголы не соответствуют представлению состояния объекта. Вместо этого используйте прилагательное, и ваши имена получателя / сеттера будут иметь смысл:

private boolean current;

public boolean isCurrent(){
    return current;
}

public void setCurrent(final boolean current){
    this.current = current;
}
47
ответ дан Sean Patrick Floyd 21 August 2018 в 17:04
поделиться
  • 1
    Что, если булевский не примитив? Если это Boolean, это должно быть или есть? – Arun 27 April 2017 в 15:56
  • 2
    Нет, такой метод может вернуть значение null, что приведет к исключению NullPointerException. Но я постараюсь не возвращать Boolean в первую очередь – Sean Patrick Floyd 27 April 2017 в 20:04
  • 3
    @Arun Я думаю, что он должен быть установлен / get вместо этого, если set / из-за Boolean - это объект вместо примитива, потому что он имеет 3 статистики, false, true или null. – Al-Mothafar 1 February 2018 в 09:51
Setter: public void setCurrent(boolean val)
Getter: public boolean getCurrent()

Для booleans вы также можете использовать

public boolean isCurrent()
-4
ответ дан Suraj Chandran 21 August 2018 в 17:04
поделиться
  • 1
    Почему это произошло? – Joel Sjögren 18 April 2014 в 09:48
  • 2
    Потому что OP задает вопрос о логических значениях. Геттер с префиксом «get» (read: should) никогда не используется для логических значений. – Harold 5 May 2014 в 15:40